mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-19 10:35:50 +00:00
Compare commits
181 Commits
0.30.1-rc1
...
0.31.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5d5856638 | ||
|
|
4e64e3f1dd | ||
|
|
51850ded05 | ||
|
|
76d7c1c01a | ||
|
|
dabc5567f7 | ||
|
|
5c5ee6f763 | ||
|
|
06bfcad671 | ||
|
|
73e48e6595 | ||
|
|
906ef761ba | ||
|
|
6b87a67592 | ||
|
|
e16361826e | ||
|
|
a327cecee6 | ||
|
|
64d9f7c23e | ||
|
|
4f16a1cee9 | ||
|
|
8f83f69325 | ||
|
|
1d0ca51c88 | ||
|
|
ca70f4fab1 | ||
|
|
72cdf3f555 | ||
|
|
1c68fddad7 | ||
|
|
2f3b5f6d0a | ||
|
|
5663c45a0d | ||
|
|
172356d299 | ||
|
|
2323ea4493 | ||
|
|
d6a666f4e0 | ||
|
|
6e70a6c6f5 | ||
|
|
b82be0a9b0 | ||
|
|
94a47569d6 | ||
|
|
73df97f2d0 | ||
|
|
e8b75b80c2 | ||
|
|
9ab5611c65 | ||
|
|
92391332d7 | ||
|
|
8e26b187be | ||
|
|
79ce5901f3 | ||
|
|
29a4849024 | ||
|
|
0a1731c4c9 | ||
|
|
5cac2befb0 | ||
|
|
e6d4436e9d | ||
|
|
16b1adfa86 | ||
|
|
404d58d77c | ||
|
|
6c712ff2df | ||
|
|
308aaa6f78 | ||
|
|
eb62959216 | ||
|
|
70d5c4eca7 | ||
|
|
a025d365b8 | ||
|
|
89fa10b40b | ||
|
|
34e85ccb62 | ||
|
|
77a4218a9e | ||
|
|
d8ee487c19 | ||
|
|
3605bf1f60 | ||
|
|
d3b43bfa37 | ||
|
|
bf6079797f | ||
|
|
6366f62f11 | ||
|
|
427c33dbd7 | ||
|
|
675cbb72a6 | ||
|
|
f846b1a88f | ||
|
|
4bfcd12897 | ||
|
|
d736232142 | ||
|
|
9cb02028ed | ||
|
|
0703441ee7 | ||
|
|
2c3128d9ba | ||
|
|
7837eed21b | ||
|
|
db092449f9 | ||
|
|
d321b446db | ||
|
|
78ce7a08c0 | ||
|
|
15adb73a13 | ||
|
|
f15cc6c4f6 | ||
|
|
61e6e5694c | ||
|
|
66bc0bb424 | ||
|
|
25589bacea | ||
|
|
d721d35a2d | ||
|
|
ba84fc2c77 | ||
|
|
0f7dbc7bc0 | ||
|
|
137dd351b8 | ||
|
|
ba38bfad9d | ||
|
|
be71e8afa2 | ||
|
|
de416adadd | ||
|
|
1fda99ba82 | ||
|
|
9f5b58c8ab | ||
|
|
8c11d24454 | ||
|
|
924b6b663e | ||
|
|
688452d971 | ||
|
|
2f94e16359 | ||
|
|
fbf736f169 | ||
|
|
f0624581d1 | ||
|
|
cb23352a35 | ||
|
|
9fea06ad84 | ||
|
|
2beeb9a293 | ||
|
|
1e92ac3cf5 | ||
|
|
acaf91a2f7 | ||
|
|
41125a0a34 | ||
|
|
35ed095dbf | ||
|
|
ce31e26f58 | ||
|
|
2b640532f2 | ||
|
|
c717006c44 | ||
|
|
fd33d693c4 | ||
|
|
31ecb4dcf3 | ||
|
|
5a4e900a21 | ||
|
|
94ed5b3a53 | ||
|
|
2eaf211e9b | ||
|
|
ed9f5639a8 | ||
|
|
8e842b5893 | ||
|
|
1b378172b6 | ||
|
|
0dc911c091 | ||
|
|
2be11874e3 | ||
|
|
5ac744ff66 | ||
|
|
57d6ab091c | ||
|
|
f13668371e | ||
|
|
c9486863c3 | ||
|
|
e9e0277b7c | ||
|
|
b69f0356ec | ||
|
|
4d72fc225a | ||
|
|
9786e432f8 | ||
|
|
040d7ebb46 | ||
|
|
f9f2b8124d | ||
|
|
dd5d938aa3 | ||
|
|
7c82adcc84 | ||
|
|
bdb1966573 | ||
|
|
a1582c610e | ||
|
|
2f9f217c11 | ||
|
|
278f679bb1 | ||
|
|
96bc727fcb | ||
|
|
7d2809eb27 | ||
|
|
5062e65277 | ||
|
|
bd44880d5a | ||
|
|
ad2383bd4b | ||
|
|
5b5a01989c | ||
|
|
c17f7e8b37 | ||
|
|
9b8133f65f | ||
|
|
77c0236cae | ||
|
|
07c4262392 | ||
|
|
10a5421987 | ||
|
|
48f0e1f51d | ||
|
|
9063953ee7 | ||
|
|
7315d9c300 | ||
|
|
05c248f297 | ||
|
|
b92a58d11e | ||
|
|
767d253593 | ||
|
|
78e59191ed | ||
|
|
de4d872b7a | ||
|
|
77955c74bc | ||
|
|
555cd59a59 | ||
|
|
b4f8dc7abf | ||
|
|
14dde47173 | ||
|
|
4fb6bf3e67 | ||
|
|
f73c55a922 | ||
|
|
49c86768e6 | ||
|
|
0fca91c6c1 | ||
|
|
749b4adc7c | ||
|
|
a67e4ab9f1 | ||
|
|
e0b2a26805 | ||
|
|
6c5b23b317 | ||
|
|
8da2a724fb | ||
|
|
d5363d1a85 | ||
|
|
8f74ee1d96 | ||
|
|
796ee8e3de | ||
|
|
25f611d0ec | ||
|
|
08e518af73 | ||
|
|
5f4fe9fccb | ||
|
|
db9885e1fc | ||
|
|
27673c1c3f | ||
|
|
3394129894 | ||
|
|
57625e06ed | ||
|
|
bdfb5fa2bc | ||
|
|
b2c9179100 | ||
|
|
d7935192dd | ||
|
|
97d5325468 | ||
|
|
8433851652 | ||
|
|
f7b2b84ece | ||
|
|
8be67c1766 | ||
|
|
4d2e7ed404 | ||
|
|
e1018546ac | ||
|
|
44fcab1081 | ||
|
|
6dab1657b1 | ||
|
|
60ad21ae0d | ||
|
|
3974ddd8f7 | ||
|
|
e0af6ec567 | ||
|
|
0a96f3a249 | ||
|
|
40363f96a9 | ||
|
|
1c9577a1ac | ||
|
|
a7a30396be | ||
|
|
fee19390f5 |
79
Builds/Ubuntu/build_clang_libs.sh
Executable file
79
Builds/Ubuntu/build_clang_libs.sh
Executable file
@@ -0,0 +1,79 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
#
|
||||||
|
# This scripts installs boost and protobuf built with clang. This is needed on
|
||||||
|
# ubuntu 15.10 when building with clang
|
||||||
|
# It will build these in a 'clang' subdirectory that it creates below the directory
|
||||||
|
# this script is run from. If a clang directory already exists the script will refuse
|
||||||
|
# to run.
|
||||||
|
|
||||||
|
if hash lsb_release 2>/dev/null; then
|
||||||
|
if [ $(lsb_release -si) == "Ubuntu" ]; then
|
||||||
|
ubuntu_release=$(lsb_release -sr)
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${ubuntu_release}" ]; then
|
||||||
|
echo "System not supported"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! hash clang 2>/dev/null; then
|
||||||
|
clang_version=3.7
|
||||||
|
sudo apt-get -y install clang-${clang_version}
|
||||||
|
update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${clang_version} 99 clang++
|
||||||
|
hash -r
|
||||||
|
if ! hash clang 2>/dev/null; then
|
||||||
|
echo "Please install clang"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ${ubuntu_release} != "15.10" ]; then
|
||||||
|
echo "clang specific boost and protobuf not needed"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d clang ]; then
|
||||||
|
echo "clang directory already exists. Cowardly refusing to run"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! hash wget 2>/dev/null; then
|
||||||
|
sudo apt-get -y install wget
|
||||||
|
hash -r
|
||||||
|
if ! hash wget 2>/dev/null; then
|
||||||
|
echo "Please install wget"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
num_procs=$(lscpu -p | grep -v '^#' | sort -u -t, -k 2,4 | wc -l) # pysical cores
|
||||||
|
|
||||||
|
mkdir clang
|
||||||
|
pushd clang > /dev/null
|
||||||
|
|
||||||
|
# Install protobuf
|
||||||
|
pb=protobuf-2.6.1
|
||||||
|
pb_tar=${pb}.tar.gz
|
||||||
|
wget -O ${pb_tar} https://github.com/google/protobuf/releases/download/v2.6.1/${pb_tar}
|
||||||
|
tar xf ${pb_tar}
|
||||||
|
rm ${pb_tar}
|
||||||
|
pushd ${pb} > /dev/null
|
||||||
|
./configure CC=clang CXX=clang++ CXXFLAGS='-std=c++14 -O3 -g'
|
||||||
|
make -j${num_procs}
|
||||||
|
popd > /dev/null
|
||||||
|
|
||||||
|
# Install boost
|
||||||
|
boost_ver=1.60.0
|
||||||
|
bd=boost_${boost_ver//./_}
|
||||||
|
bd_tar=${bd}.tar.gz
|
||||||
|
wget -O ${bd_tar} http://sourceforge.net/projects/boost/files/boost/${boost_ver}/${bd_tar}
|
||||||
|
tar xf ${bd_tar}
|
||||||
|
rm ${bd_tar}
|
||||||
|
pushd ${bd} > /dev/null
|
||||||
|
./bootstrap.sh
|
||||||
|
./b2 toolset=clang -j${num_procs}
|
||||||
|
popd > /dev/null
|
||||||
|
|
||||||
|
popd > /dev/null
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
113
SConstruct
113
SConstruct
@@ -61,10 +61,16 @@ The following environment variables modify the build environment:
|
|||||||
Path to the boost directory.
|
Path to the boost directory.
|
||||||
OPENSSL_ROOT
|
OPENSSL_ROOT
|
||||||
Path to the openssl directory.
|
Path to the openssl directory.
|
||||||
PROTOBUF_DIR
|
PROTOBUF_ROOT
|
||||||
Path to the protobuf directory. This is usually only needed when
|
Path to the protobuf directory.
|
||||||
the installed protobuf library uses a different ABI than clang
|
CLANG_PROTOBUF_ROOT
|
||||||
(as with ubuntu 15.10).
|
Override the path to the protobuf directory for the clang toolset. This is
|
||||||
|
usually only needed when the installed protobuf library uses a different
|
||||||
|
ABI than clang (as with ubuntu 15.10).
|
||||||
|
CLANG_BOOST_ROOT
|
||||||
|
Override the path to the boost directory for the clang toolset. This is
|
||||||
|
usually only needed when the installed protobuf library uses a different
|
||||||
|
ABI than clang (as with ubuntu 15.10).
|
||||||
|
|
||||||
The following extra options may be used:
|
The following extra options may be used:
|
||||||
--ninja Generate a `build.ninja` build file for the specified target
|
--ninja Generate a `build.ninja` build file for the specified target
|
||||||
@@ -73,6 +79,8 @@ The following extra options may be used:
|
|||||||
|
|
||||||
--static On linux, link protobuf, openssl, libc++, and boost statically
|
--static On linux, link protobuf, openssl, libc++, and boost statically
|
||||||
|
|
||||||
|
--sanitize=[address, thread] On gcc & clang, add sanitizer instrumentation
|
||||||
|
|
||||||
GCC 5: If the gcc toolchain is used, gcc version 5 or better is required. On
|
GCC 5: If the gcc toolchain is used, gcc version 5 or better is required. On
|
||||||
linux distros that ship with gcc 4 (ubuntu < 15.10), rippled will force gcc
|
linux distros that ship with gcc 4 (ubuntu < 15.10), rippled will force gcc
|
||||||
to use gcc4's ABI (there was an ABI change between versions). This allows us
|
to use gcc4's ABI (there was an ABI change between versions). This allows us
|
||||||
@@ -122,6 +130,9 @@ import scons_to_ninja
|
|||||||
AddOption('--ninja', dest='ninja', action='store_true',
|
AddOption('--ninja', dest='ninja', action='store_true',
|
||||||
help='generate ninja build file build.ninja')
|
help='generate ninja build file build.ninja')
|
||||||
|
|
||||||
|
AddOption('--sanitize', dest='sanitize', choices=['address', 'thread'],
|
||||||
|
help='Build with sanitizer support (gcc and clang only).')
|
||||||
|
|
||||||
AddOption('--static', dest='static', action='store_true',
|
AddOption('--static', dest='static', action='store_true',
|
||||||
help='On linux, link protobuf, openssl, libc++, and boost statically')
|
help='On linux, link protobuf, openssl, libc++, and boost statically')
|
||||||
|
|
||||||
@@ -348,24 +359,9 @@ def config_base(env):
|
|||||||
,{'HAVE_USLEEP' : '1'}
|
,{'HAVE_USLEEP' : '1'}
|
||||||
,{'SOCI_CXX_C11' : '1'}
|
,{'SOCI_CXX_C11' : '1'}
|
||||||
,'_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS'
|
,'_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS'
|
||||||
,'-DBOOST_NO_AUTO_PTR'
|
,'BOOST_NO_AUTO_PTR'
|
||||||
])
|
])
|
||||||
|
|
||||||
try:
|
|
||||||
BOOST_ROOT = os.path.normpath(os.environ['BOOST_ROOT'])
|
|
||||||
env.Append(LIBPATH=[
|
|
||||||
os.path.join(BOOST_ROOT, 'stage', 'lib'),
|
|
||||||
])
|
|
||||||
env['BOOST_ROOT'] = BOOST_ROOT
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
try:
|
|
||||||
protobuf_dir = os.environ['PROTOBUF_DIR']
|
|
||||||
env.Append(LIBPATH=[protobuf_dir])
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if Beast.system.windows:
|
if Beast.system.windows:
|
||||||
try:
|
try:
|
||||||
OPENSSL_ROOT = os.path.normpath(os.environ['OPENSSL_ROOT'])
|
OPENSSL_ROOT = os.path.normpath(os.environ['OPENSSL_ROOT'])
|
||||||
@@ -400,7 +396,7 @@ def add_static_libs(env, static_libs, dyn_libs=None):
|
|||||||
for k,l in [('STATICLIBS', static_libs or []), ('DYNAMICLIBS', dyn_libs or [])]:
|
for k,l in [('STATICLIBS', static_libs or []), ('DYNAMICLIBS', dyn_libs or [])]:
|
||||||
c = env.get(k, '')
|
c = env.get(k, '')
|
||||||
for f in l:
|
for f in l:
|
||||||
c += ' -l' + f
|
c += ' -l' + f
|
||||||
env[k] = c
|
env[k] = c
|
||||||
|
|
||||||
def get_libs(lib, static):
|
def get_libs(lib, static):
|
||||||
@@ -425,33 +421,77 @@ def get_libs(lib, static):
|
|||||||
else:
|
else:
|
||||||
static_libs.append(l)
|
static_libs.append(l)
|
||||||
return (static_libs, dynamic_libs)
|
return (static_libs, dynamic_libs)
|
||||||
except:
|
except Exception as e:
|
||||||
raise Exception('pkg-config failed for ' + lib)
|
raise Exception('pkg-config failed for ' + lib + '; Exception: ' + str(e))
|
||||||
|
|
||||||
# Set toolchain and variant specific construction variables
|
def add_sanitizer (toolchain, env):
|
||||||
def config_env(toolchain, variant, env):
|
san = GetOption('sanitize')
|
||||||
if is_debug_variant(variant):
|
if not san: return
|
||||||
env.Append(CPPDEFINES=['DEBUG', '_DEBUG'])
|
san_to_lib = {'address': 'asan', 'thread': 'tsan'}
|
||||||
|
if toolchain not in Split('clang gcc'):
|
||||||
|
raise Exception("Sanitizers are only supported for gcc and clang")
|
||||||
|
env.Append(CCFLAGS=['-fsanitize='+san, '-fno-omit-frame-pointer'])
|
||||||
|
env.Append(LINKFLAGS=['-fsanitize='+san])
|
||||||
|
add_static_libs(env, [san_to_lib[san]])
|
||||||
|
env.Append(CPPDEFINES=['SANITIZER='+san_to_lib[san].upper()])
|
||||||
|
|
||||||
elif variant == 'release' or variant == 'profile':
|
def add_boost_and_protobuf(toolchain, env):
|
||||||
env.Append(CPPDEFINES=['NDEBUG'])
|
def get_environ_value(candidates):
|
||||||
|
for c in candidates:
|
||||||
|
try:
|
||||||
|
return os.environ[c]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
raise KeyError('Environment variable not set')
|
||||||
|
|
||||||
if 'BOOST_ROOT' in env:
|
try:
|
||||||
|
br_cands = ['CLANG_BOOST_ROOT'] if toolchain == 'clang' else []
|
||||||
|
br_cands.append('BOOST_ROOT')
|
||||||
|
BOOST_ROOT = os.path.normpath(get_environ_value(br_cands))
|
||||||
|
env.Append(LIBPATH=[
|
||||||
|
os.path.join(BOOST_ROOT, 'stage', 'lib'),
|
||||||
|
])
|
||||||
|
env['BOOST_ROOT'] = BOOST_ROOT
|
||||||
if toolchain == 'gcc':
|
if toolchain == 'gcc':
|
||||||
env.Append(CCFLAGS=['-isystem' + env['BOOST_ROOT']])
|
env.Append(CCFLAGS=['-isystem' + env['BOOST_ROOT']])
|
||||||
else:
|
else:
|
||||||
env.Append(CPPPATH=[
|
env.Append(CPPPATH=[
|
||||||
env['BOOST_ROOT'],
|
env['BOOST_ROOT'],
|
||||||
])
|
])
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
pb_cands = ['CLANG_PROTOBUF_ROOT'] if toolchain == 'clang' else []
|
||||||
|
pb_cands.append('PROTOBUF_ROOT')
|
||||||
|
PROTOBUF_ROOT = os.path.normpath(get_environ_value(pb_cands))
|
||||||
|
env.Append(LIBPATH=[PROTOBUF_ROOT + '/src/.libs'])
|
||||||
|
if not should_link_static() and toolchain in['clang', 'gcc']:
|
||||||
|
env.Append(LINKFLAGS=['-Wl,-rpath,' + PROTOBUF_ROOT + '/src/.libs'])
|
||||||
|
env['PROTOBUF_ROOT'] = PROTOBUF_ROOT
|
||||||
|
env.Append(CPPPATH=[env['PROTOBUF_ROOT'] + '/src',])
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Set toolchain and variant specific construction variables
|
||||||
|
def config_env(toolchain, variant, env):
|
||||||
|
add_boost_and_protobuf(toolchain, env)
|
||||||
|
if is_debug_variant(variant):
|
||||||
|
env.Append(CPPDEFINES=['DEBUG', '_DEBUG'])
|
||||||
|
|
||||||
|
elif variant == 'release' or variant == 'profile':
|
||||||
|
env.Append(CPPDEFINES=['NDEBUG'])
|
||||||
|
|
||||||
if should_link_static() and not Beast.system.linux:
|
if should_link_static() and not Beast.system.linux:
|
||||||
raise Exception("Static linking is only implemented for linux.")
|
raise Exception("Static linking is only implemented for linux.")
|
||||||
|
|
||||||
|
add_sanitizer(toolchain, env)
|
||||||
|
|
||||||
if toolchain in Split('clang gcc'):
|
if toolchain in Split('clang gcc'):
|
||||||
if Beast.system.linux:
|
if Beast.system.linux:
|
||||||
link_static = should_link_static()
|
link_static = should_link_static()
|
||||||
for l in ['openssl', 'protobuf']:
|
for l in ['openssl', 'protobuf']:
|
||||||
static, dynamic = get_libs(l, link_static)
|
static, dynamic = get_libs(l, link_static)
|
||||||
if link_static:
|
if link_static:
|
||||||
add_static_libs(env, static, dynamic)
|
add_static_libs(env, static, dynamic)
|
||||||
else:
|
else:
|
||||||
@@ -643,6 +683,7 @@ def config_env(toolchain, variant, env):
|
|||||||
'_SCL_SECURE_NO_WARNINGS',
|
'_SCL_SECURE_NO_WARNINGS',
|
||||||
'_CRT_SECURE_NO_WARNINGS',
|
'_CRT_SECURE_NO_WARNINGS',
|
||||||
'WIN32_CONSOLE',
|
'WIN32_CONSOLE',
|
||||||
|
'NOMINMAX'
|
||||||
])
|
])
|
||||||
if variant == 'debug':
|
if variant == 'debug':
|
||||||
env.Append(LIBS=[
|
env.Append(LIBS=[
|
||||||
@@ -864,8 +905,8 @@ def get_classic_sources(toolchain):
|
|||||||
append_sources(result, *list_sources('src/ripple/protocol', '.cpp'))
|
append_sources(result, *list_sources('src/ripple/protocol', '.cpp'))
|
||||||
append_sources(result, *list_sources('src/ripple/rpc', '.cpp'))
|
append_sources(result, *list_sources('src/ripple/rpc', '.cpp'))
|
||||||
append_sources(result, *list_sources('src/ripple/shamap', '.cpp'))
|
append_sources(result, *list_sources('src/ripple/shamap', '.cpp'))
|
||||||
|
append_sources(result, *list_sources('src/ripple/server', '.cpp'))
|
||||||
append_sources(result, *list_sources('src/ripple/test', '.cpp'))
|
append_sources(result, *list_sources('src/ripple/test', '.cpp'))
|
||||||
append_sources(result, *list_sources('src/ripple/unl', '.cpp'))
|
|
||||||
|
|
||||||
if use_shp(toolchain):
|
if use_shp(toolchain):
|
||||||
cc_flags = {'CCFLAGS': ['--system-header-prefix=rocksdb2']}
|
cc_flags = {'CCFLAGS': ['--system-header-prefix=rocksdb2']}
|
||||||
@@ -908,8 +949,8 @@ def get_unity_sources(toolchain):
|
|||||||
'src/ripple/unity/protocol.cpp',
|
'src/ripple/unity/protocol.cpp',
|
||||||
'src/ripple/unity/rpcx.cpp',
|
'src/ripple/unity/rpcx.cpp',
|
||||||
'src/ripple/unity/shamap.cpp',
|
'src/ripple/unity/shamap.cpp',
|
||||||
|
'src/ripple/unity/server.cpp',
|
||||||
'src/ripple/unity/test.cpp',
|
'src/ripple/unity/test.cpp',
|
||||||
'src/ripple/unity/unl.cpp',
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if use_shp(toolchain):
|
if use_shp(toolchain):
|
||||||
@@ -1054,7 +1095,6 @@ for tu_style in ['classic', 'unity']:
|
|||||||
'src/ripple/unity/protobuf.cpp',
|
'src/ripple/unity/protobuf.cpp',
|
||||||
'src/ripple/unity/ripple.proto.cpp',
|
'src/ripple/unity/ripple.proto.cpp',
|
||||||
'src/ripple/unity/resource.cpp',
|
'src/ripple/unity/resource.cpp',
|
||||||
'src/ripple/unity/server.cpp',
|
|
||||||
'src/ripple/unity/websocket02.cpp',
|
'src/ripple/unity/websocket02.cpp',
|
||||||
**cc_flags
|
**cc_flags
|
||||||
)
|
)
|
||||||
@@ -1097,11 +1137,6 @@ for tu_style in ['classic', 'unity']:
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
object_builder.add_source_files(
|
|
||||||
'src/ripple/unity/websocket04.cpp',
|
|
||||||
CPPPATH='src/websocketpp',
|
|
||||||
)
|
|
||||||
|
|
||||||
if toolchain == "clang" and Beast.system.osx:
|
if toolchain == "clang" and Beast.system.osx:
|
||||||
object_builder.add_source_files('src/ripple/unity/beastobjc.mm')
|
object_builder.add_source_files('src/ripple/unity/beastobjc.mm')
|
||||||
|
|
||||||
|
|||||||
@@ -83,5 +83,5 @@ test_script:
|
|||||||
- build\\rippled --unittest
|
- build\\rippled --unittest
|
||||||
|
|
||||||
# Run the integration tests
|
# Run the integration tests
|
||||||
- npm install
|
- npm install --progress=false
|
||||||
- npm test
|
- npm test
|
||||||
|
|||||||
@@ -37,5 +37,5 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Run NPM tests
|
# Run NPM tests
|
||||||
npm install
|
npm install --progress=false
|
||||||
npm test --rippled=$RIPPLED_PATH
|
npm test --rippled=$RIPPLED_PATH
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ Usage:
|
|||||||
sign <sequence> <validator-public> <master-secret>
|
sign <sequence> <validator-public> <master-secret>
|
||||||
Create a new signed manifest with the given sequence
|
Create a new signed manifest with the given sequence
|
||||||
number, validator public key, and master secret key.
|
number, validator public key, and master secret key.
|
||||||
|
|
||||||
|
verify <sequence> <validator-public> <signature> <master-public>
|
||||||
|
Verify hex-encoded manifest signature with master public key.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def prepend_length_byte(b):
|
def prepend_length_byte(b):
|
||||||
@@ -113,6 +116,16 @@ def get_signature(seq, validator_public_key_human, private_key_human):
|
|||||||
m1 = sign_manifest(m, private_key, pk)
|
m1 = sign_manifest(m, private_key, pk)
|
||||||
return base64.b64encode(m1)
|
return base64.b64encode(m1)
|
||||||
|
|
||||||
|
def verify_signature(seq, validator_public_key_human, public_key_human, signature):
|
||||||
|
v, validator_public_key = Base58.decode_version(validator_public_key_human)
|
||||||
|
check_validator_public(v, validator_public_key)
|
||||||
|
|
||||||
|
v, public_key = Base58.decode_version(public_key_human)
|
||||||
|
|
||||||
|
m = make_manifest(public_key, validator_public_key, seq)
|
||||||
|
public_key = public_key[1:] # Remove ED25519_BYTE
|
||||||
|
sig = signature.decode('hex')
|
||||||
|
ed25519.checkvalid(sig, 'MAN\0' + m, public_key)
|
||||||
|
|
||||||
# Testable versions of functions.
|
# Testable versions of functions.
|
||||||
def perform_create(urandom=os.urandom, print=print):
|
def perform_create(urandom=os.urandom, print=print):
|
||||||
@@ -131,6 +144,12 @@ def perform_sign(
|
|||||||
print(wrap(get_signature(
|
print(wrap(get_signature(
|
||||||
int(seq), validator_public_key_human, private_key_human)))
|
int(seq), validator_public_key_human, private_key_human)))
|
||||||
|
|
||||||
|
def perform_verify(
|
||||||
|
seq, validator_public_key_human, public_key_human, signature, print=print):
|
||||||
|
verify_signature(
|
||||||
|
int(seq), validator_public_key_human, public_key_human, signature)
|
||||||
|
print('Signature valid for', public_key_human)
|
||||||
|
|
||||||
# Externally visible versions of functions.
|
# Externally visible versions of functions.
|
||||||
def create():
|
def create():
|
||||||
perform_create()
|
perform_create()
|
||||||
@@ -141,6 +160,8 @@ def check(s):
|
|||||||
def sign(seq, validator_public_key_human, private_key_human):
|
def sign(seq, validator_public_key_human, private_key_human):
|
||||||
perform_sign(seq, validator_public_key_human, private_key_human)
|
perform_sign(seq, validator_public_key_human, private_key_human)
|
||||||
|
|
||||||
|
def verify(seq, validator_public_key_human, public_key_human, signature):
|
||||||
|
perform_verify(seq, validator_public_key_human, public_key_human, signature)
|
||||||
|
|
||||||
def usage(*errors):
|
def usage(*errors):
|
||||||
if errors:
|
if errors:
|
||||||
@@ -148,7 +169,7 @@ def usage(*errors):
|
|||||||
print(USAGE)
|
print(USAGE)
|
||||||
return not errors
|
return not errors
|
||||||
|
|
||||||
_COMMANDS = dict((f.__name__, f) for f in (create, check, sign))
|
_COMMANDS = dict((f.__name__, f) for f in (create, check, sign, verify))
|
||||||
|
|
||||||
def run_command(args):
|
def run_command(args):
|
||||||
if not args:
|
if not args:
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ class test_Sign(TestCase):
|
|||||||
'JAAAABdxIe2DIKUZd9jDjKikknxnDfWCHkSXYZReFenvsmoVCdIw6nMhAnZ2dnZ2'
|
'JAAAABdxIe2DIKUZd9jDjKikknxnDfWCHkSXYZReFenvsmoVCdIw6nMhAnZ2dnZ2'
|
||||||
'dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dkDOjlWtQSvRTjuwe+4iNusg0sJM'
|
'dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dkDOjlWtQSvRTjuwe+4iNusg0sJM'
|
||||||
'zqkBJwDz30b2SkxZ7Fte/Vx4htM/kkfUfJCaxmxE5N4dHSKuiO9iDHsktqIA')
|
'zqkBJwDz30b2SkxZ7Fte/Vx4htM/kkfUfJCaxmxE5N4dHSKuiO9iDHsktqIA')
|
||||||
|
VALIDATOR_KEY_HUMAN = 'n9JijuoCv8ubEy5ag3LiX3hyq27GaLJsitZPbQ6APkwx2MkUXq8E'
|
||||||
|
SIGNATURE_HEX = (
|
||||||
|
'0a1546caa29c887f9fcb5e6143ea101b31fb5895a5cdfa24939301c66ff51794'
|
||||||
|
'a0b729e0ebbf576f2cc7cdb9f68c2366324a53b8e1ecf16f3c17bebbdb8d7102')
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.results = []
|
self.results = []
|
||||||
@@ -96,6 +100,11 @@ class test_Sign(TestCase):
|
|||||||
'dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dkDOjlWtQSvRTjuwe+4iNusg0sJM'
|
'dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dkDOjlWtQSvRTjuwe+4iNusg0sJM'
|
||||||
'zqkBJwDz30b2SkxZ7Fte/Vx4htM/kkfUfJCaxmxE5N4dHSKuiO9iDHsktqIA')
|
'zqkBJwDz30b2SkxZ7Fte/Vx4htM/kkfUfJCaxmxE5N4dHSKuiO9iDHsktqIA')
|
||||||
|
|
||||||
|
def test_verify_signature(self):
|
||||||
|
Sign.verify_signature(self.SEQUENCE, self.VALIDATOR_KEY_HUMAN,
|
||||||
|
'nHUUaKHpxyRP4TZZ79tTpXuTpoM8pRNs5crZpGVA5jdrjib5easY',
|
||||||
|
self.SIGNATURE_HEX)
|
||||||
|
|
||||||
def test_check(self):
|
def test_check(self):
|
||||||
public = Base58.encode_version(Base58.VER_NODE_PRIVATE, 32 * 'k')
|
public = Base58.encode_version(Base58.VER_NODE_PRIVATE, 32 * 'k')
|
||||||
Sign.perform_check(public, self.print)
|
Sign.perform_check(public, self.print)
|
||||||
@@ -125,3 +134,8 @@ class test_Sign(TestCase):
|
|||||||
'Z2dnZ2dkDOjlWtQSvRTjuwe+4iNusg0sJMzqkBJwDz30b2S\n'
|
'Z2dnZ2dkDOjlWtQSvRTjuwe+4iNusg0sJMzqkBJwDz30b2S\n'
|
||||||
'kxZ7Fte/Vx4htM/kkfUfJCaxmxE5N4dHSKuiO9iDHsktqIA'],
|
'kxZ7Fte/Vx4htM/kkfUfJCaxmxE5N4dHSKuiO9iDHsktqIA'],
|
||||||
{}]])
|
{}]])
|
||||||
|
|
||||||
|
def test_verify(self):
|
||||||
|
Sign.perform_verify(self.SEQUENCE, self.VALIDATOR_KEY_HUMAN,
|
||||||
|
'nHUUaKHpxyRP4TZZ79tTpXuTpoM8pRNs5crZpGVA5jdrjib5easY',
|
||||||
|
self.SIGNATURE_HEX, print=self.print)
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ test:
|
|||||||
# gdb segfaults
|
# gdb segfaults
|
||||||
# - cat script.gdb | gdb --ex 'set print thread-events off' --return-child-result --args build/clang.debug/rippled --unittest
|
# - cat script.gdb | gdb --ex 'set print thread-events off' --return-child-result --args build/clang.debug/rippled --unittest
|
||||||
- build/clang.debug/rippled --unittest
|
- build/clang.debug/rippled --unittest
|
||||||
- npm install
|
- npm install --progress=false
|
||||||
# Use build/(gcc|clang).debug/rippled
|
# Use build/(gcc|clang).debug/rippled
|
||||||
- |
|
- |
|
||||||
echo "exports.default_server_config = {\"rippled_path\" : \"$HOME/rippled/build/clang.debug/rippled\"};" > test/config.js
|
echo "exports.default_server_config = {\"rippled_path\" : \"$HOME/rippled/build/clang.debug/rippled\"};" > test/config.js
|
||||||
|
|||||||
@@ -503,17 +503,11 @@
|
|||||||
#
|
#
|
||||||
# [validators]
|
# [validators]
|
||||||
#
|
#
|
||||||
# List of nodes to always accept as validators. Nodes are specified by domain
|
# List of the validation public keys of nodes to always accept as validators.
|
||||||
# or public key.
|
# A comment may, optionally, be associated with each entry, separated by
|
||||||
#
|
# whitespace from the validation public key.
|
||||||
# For domains, rippled will probe for https web servers at the specified
|
|
||||||
# domain in the following order: ripple.DOMAIN, www.DOMAIN, DOMAIN
|
|
||||||
#
|
|
||||||
# For public key entries, a comment may optionally be specified after adding
|
|
||||||
# a space to the public key.
|
|
||||||
#
|
#
|
||||||
# Examples:
|
# Examples:
|
||||||
# ripple.com
|
|
||||||
# n9KorY8QtTdRx7TVDpwnG9NvyxsDwHUKUEeDLY3AkiGncVaSXZi5
|
# n9KorY8QtTdRx7TVDpwnG9NvyxsDwHUKUEeDLY3AkiGncVaSXZi5
|
||||||
# n9MqiExBcoG19UXwoLjBJnhsxEhAZMuWwJDRdkyDz1EkEkwzQTNt John Doe
|
# n9MqiExBcoG19UXwoLjBJnhsxEhAZMuWwJDRdkyDz1EkEkwzQTNt John Doe
|
||||||
#
|
#
|
||||||
@@ -521,33 +515,27 @@
|
|||||||
#
|
#
|
||||||
# [validators_file]
|
# [validators_file]
|
||||||
#
|
#
|
||||||
# Path to file contain a list of nodes to always accept as validators. Use
|
# Path to a file that contains the validation public keys of nodes to always
|
||||||
# this to specify a file other than this file to manage your validators list.
|
# accept as validators. A comment may, optionally, be associated with each
|
||||||
|
# entry, separated by whitespace from the validation public key.
|
||||||
#
|
#
|
||||||
# If this entry is not present or empty and no nodes from previous runs were
|
# The contents of the file should include a [validators] entry, followed by
|
||||||
# found in the database, rippled will look for a validators.txt in the config
|
# a list of validation public keys of nodes to always accept as validators,
|
||||||
# directory. If not found there, it will attempt to retrieve the file from
|
# one per line, optionally followed by a comment separated by whitespace:
|
||||||
# the [validators_site] web site.
|
|
||||||
#
|
|
||||||
# After specifying a different [validators_file] or changing the contents of
|
|
||||||
# the validators file, issue a RPC unl_load command to have rippled load the
|
|
||||||
# file.
|
|
||||||
#
|
#
|
||||||
# Specify the file by specifying its full path.
|
# Specify the file by specifying its full path.
|
||||||
#
|
#
|
||||||
# Examples:
|
# Examples:
|
||||||
# C:/home/johndoe/ripple/validators.txt
|
# /home/ripple/validators.txt
|
||||||
# /home/johndoe/ripple/validators.txt
|
# C:/home/ripple/validators.txt
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# [validators_site]
|
|
||||||
#
|
|
||||||
# Specifies where to find validators.txt for UNL boostrapping and RPC
|
|
||||||
# unl_network command.
|
|
||||||
#
|
|
||||||
# Example: ripple.com
|
|
||||||
#
|
#
|
||||||
|
# Example content:
|
||||||
|
# [validators]
|
||||||
|
# n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7 RL1
|
||||||
|
# n9MD5h24qrQqiyBC8aeqqCWvpiBiYQ3jxSr91uiDvmrkyHRdYLUj RL2
|
||||||
|
# n9L81uNCaPgtUJfaHh89gmdvXKAmSt5Gdsw2g1iPWaPkAHW5Nm4C RL3
|
||||||
|
# n9KiYM9CgngLvtRCQHZwgC2gjpdaZcCcbt3VboxiNFcKuwFVujzS RL4
|
||||||
|
# n9LdgEtkmGB9E2h3K4Vp7iGUaKuq23Zr32ehxiU8FWY7xoxbWTSA RL5
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# [path_search]
|
# [path_search]
|
||||||
|
|||||||
@@ -149,13 +149,6 @@
|
|||||||
#define RIPPLE_USE_VALIDATORS 0
|
#define RIPPLE_USE_VALIDATORS 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** Config: RIPPLE_PROPOSE_FEATURES
|
|
||||||
This determines whether to add any features to the proposed transaction set.
|
|
||||||
*/
|
|
||||||
#ifndef RIPPLE_PROPOSE_AMENDMENTS
|
|
||||||
#define RIPPLE_PROPOSE_AMENDMENTS 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Config: RIPPLE_SINGLE_IO_SERVICE_THREAD
|
/** Config: RIPPLE_SINGLE_IO_SERVICE_THREAD
|
||||||
When set, restricts the number of threads calling io_service::run to one.
|
When set, restricts the number of threads calling io_service::run to one.
|
||||||
This is useful when debugging.
|
This is useful when debugging.
|
||||||
|
|||||||
@@ -1,106 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Portions of this file are from JUCE.
|
|
||||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
|
||||||
Please visit http://www.juce.com
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_ARITHMETIC_H_INCLUDED
|
|
||||||
#define BEAST_ARITHMETIC_H_INCLUDED
|
|
||||||
|
|
||||||
#include <beast/Config.h>
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Constrains a value to keep it within a given range.
|
|
||||||
|
|
||||||
This will check that the specified value lies between the lower and upper bounds
|
|
||||||
specified, and if not, will return the nearest value that would be in-range. Effectively,
|
|
||||||
it's like calling bmax (lowerLimit, bmin (upperLimit, value)).
|
|
||||||
|
|
||||||
Note that it expects that lowerLimit <= upperLimit. If this isn't true,
|
|
||||||
the results will be unpredictable.
|
|
||||||
|
|
||||||
@param lowerLimit the minimum value to return
|
|
||||||
@param upperLimit the maximum value to return
|
|
||||||
@param valueToConstrain the value to try to return
|
|
||||||
@returns the closest value to valueToConstrain which lies between lowerLimit
|
|
||||||
and upperLimit (inclusive)
|
|
||||||
@see blimit0To, bmin, bmax
|
|
||||||
*/
|
|
||||||
template <typename Type>
|
|
||||||
inline Type blimit (const Type lowerLimit,
|
|
||||||
const Type upperLimit,
|
|
||||||
const Type valueToConstrain) noexcept
|
|
||||||
{
|
|
||||||
// if these are in the wrong order, results are unpredictable.
|
|
||||||
bassert (lowerLimit <= upperLimit);
|
|
||||||
|
|
||||||
return (valueToConstrain < lowerLimit) ? lowerLimit
|
|
||||||
: ((upperLimit < valueToConstrain) ? upperLimit
|
|
||||||
: valueToConstrain);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns true if a value is at least zero, and also below a specified upper limit.
|
|
||||||
This is basically a quicker way to write:
|
|
||||||
@code valueToTest >= 0 && valueToTest < upperLimit
|
|
||||||
@endcode
|
|
||||||
*/
|
|
||||||
template <typename Type>
|
|
||||||
inline bool isPositiveAndBelow (Type valueToTest, Type upperLimit) noexcept
|
|
||||||
{
|
|
||||||
bassert (Type() <= upperLimit); // makes no sense to call this if the upper limit is itself below zero..
|
|
||||||
return Type() <= valueToTest && valueToTest < upperLimit;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline bool isPositiveAndBelow (const int valueToTest, const int upperLimit) noexcept
|
|
||||||
{
|
|
||||||
bassert (upperLimit >= 0); // makes no sense to call this if the upper limit is itself below zero..
|
|
||||||
return static_cast <unsigned int> (valueToTest) < static_cast <unsigned int> (upperLimit);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
/** Handy function for getting the number of elements in a simple const C array.
|
|
||||||
E.g.
|
|
||||||
@code
|
|
||||||
static int myArray[] = { 1, 2, 3 };
|
|
||||||
|
|
||||||
int numElements = numElementsInArray (myArray) // returns 3
|
|
||||||
@endcode
|
|
||||||
*/
|
|
||||||
template <typename Type, int N>
|
|
||||||
int numElementsInArray (Type (&array)[N])
|
|
||||||
{
|
|
||||||
(void) array; // (required to avoid a spurious warning in MS compilers)
|
|
||||||
(void) sizeof (0[array]); // This line should cause an error if you pass an object with a user-defined subscript operator
|
|
||||||
return N;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
#include <beast/chrono/abstract_clock.h>
|
#include <beast/chrono/abstract_clock.h>
|
||||||
#include <beast/chrono/basic_seconds_clock.h>
|
#include <beast/chrono/basic_seconds_clock.h>
|
||||||
#include <beast/chrono/chrono_io.h>
|
|
||||||
#include <beast/chrono/chrono_util.h>
|
#include <beast/chrono/chrono_util.h>
|
||||||
#include <beast/chrono/manual_clock.h>
|
#include <beast/chrono/manual_clock.h>
|
||||||
#include <beast/chrono/ratio_io.h>
|
#include <beast/chrono/ratio_io.h>
|
||||||
|
|||||||
@@ -40,37 +40,6 @@ template <typename Type>
|
|||||||
void zerostruct (Type& structure) noexcept
|
void zerostruct (Type& structure) noexcept
|
||||||
{ memset (&structure, 0, sizeof (structure)); }
|
{ memset (&structure, 0, sizeof (structure)); }
|
||||||
|
|
||||||
/** Delete an object pointer, and sets the pointer to null.
|
|
||||||
|
|
||||||
Remember that it's not good c++ practice to use delete directly - always try to use a std::unique_ptr
|
|
||||||
or other automatic lifetime-management system rather than resorting to deleting raw pointers!
|
|
||||||
*/
|
|
||||||
template <typename Type>
|
|
||||||
void deleteAndZero (Type& pointer)
|
|
||||||
{ delete pointer; pointer = nullptr; }
|
|
||||||
|
|
||||||
/** A handy function which adds a number of bytes to any type of pointer and returns the result.
|
|
||||||
This can be useful to avoid casting pointers to a char* and back when you want to move them by
|
|
||||||
a specific number of bytes,
|
|
||||||
*/
|
|
||||||
template <typename Type, typename IntegerType>
|
|
||||||
Type* addBytesToPointer (Type* pointer, IntegerType bytes) noexcept
|
|
||||||
{ return (Type*) (((char*) pointer) + bytes); }
|
|
||||||
|
|
||||||
/** A handy function which returns the difference between any two pointers, in bytes.
|
|
||||||
The address of the second pointer is subtracted from the first, and the difference in bytes is returned.
|
|
||||||
*/
|
|
||||||
template <typename Type1, typename Type2>
|
|
||||||
int getAddressDifference (Type1* pointer1, Type2* pointer2) noexcept
|
|
||||||
{ return (int) (((const char*) pointer1) - (const char*) pointer2); }
|
|
||||||
|
|
||||||
/** If a pointer is non-null, this returns a new copy of the object that it points to, or safely returns
|
|
||||||
nullptr if the pointer is null.
|
|
||||||
*/
|
|
||||||
template <class Type>
|
|
||||||
Type* createCopyIfNotNull (const Type* pointer)
|
|
||||||
{ return pointer != nullptr ? new Type (*pointer) : nullptr; }
|
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
#if BEAST_MAC || BEAST_IOS || DOXYGEN
|
#if BEAST_MAC || BEAST_IOS || DOXYGEN
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_STRINGS_H_INCLUDED
|
|
||||||
#define BEAST_STRINGS_H_INCLUDED
|
|
||||||
|
|
||||||
#include <beast/strings/String.h>
|
|
||||||
#include <beast/strings/NewLine.h>
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -20,15 +20,9 @@
|
|||||||
#ifndef BEAST_THREADS_H_INCLUDED
|
#ifndef BEAST_THREADS_H_INCLUDED
|
||||||
#define BEAST_THREADS_H_INCLUDED
|
#define BEAST_THREADS_H_INCLUDED
|
||||||
|
|
||||||
#include <beast/threads/UnlockGuard.h>
|
|
||||||
#include <beast/threads/TryLockGuard.h>
|
|
||||||
#include <beast/threads/SharedLockGuard.h>
|
|
||||||
#include <beast/threads/SharedMutexAdapter.h>
|
|
||||||
#include <beast/threads/SpinLock.h>
|
|
||||||
#include <beast/threads/Stoppable.h>
|
#include <beast/threads/Stoppable.h>
|
||||||
#include <beast/threads/Thread.h>
|
#include <beast/threads/Thread.h>
|
||||||
#include <beast/threads/WaitableEvent.h>
|
#include <beast/threads/WaitableEvent.h>
|
||||||
#include <beast/threads/ScopedWrapperContext.h>
|
|
||||||
|
|
||||||
#include <beast/threads/semaphore.h>
|
#include <beast/threads/semaphore.h>
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
|
|
||||||
#include <beast/Config.h>
|
#include <beast/Config.h>
|
||||||
|
|
||||||
#include <beast/chrono/impl/chrono_io.cpp>
|
|
||||||
#include <beast/chrono/impl/RelativeTime.cpp>
|
#include <beast/chrono/impl/RelativeTime.cpp>
|
||||||
|
|
||||||
#include <beast/chrono/tests/abstract_clock.test.cpp>
|
#include <beast/chrono/tests/abstract_clock.test.cpp>
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
#define BEAST_CHRONO_RELATIVETIME_H_INCLUDED
|
#define BEAST_CHRONO_RELATIVETIME_H_INCLUDED
|
||||||
|
|
||||||
#include <beast/Config.h>
|
#include <beast/Config.h>
|
||||||
#include <beast/strings/String.h>
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@@ -145,24 +144,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
value_type inWeeks() const noexcept;
|
value_type inWeeks() const noexcept;
|
||||||
|
|
||||||
/** Returns a readable textual description of the time.
|
|
||||||
|
|
||||||
The exact format of the string returned will depend on
|
|
||||||
the magnitude of the time - e.g.
|
|
||||||
|
|
||||||
"1 min 4 secs", "1 hr 45 mins", "2 weeks 5 days", "140 ms"
|
|
||||||
|
|
||||||
so that only the two most significant units are printed.
|
|
||||||
|
|
||||||
The returnValueForZeroTime value is the result that is returned if the
|
|
||||||
length is zero. Depending on your application you might want to use this
|
|
||||||
to return something more relevant like "empty" or "0 secs", etc.
|
|
||||||
|
|
||||||
@see inMilliseconds, inSeconds, inMinutes, inHours, inDays, inWeeks
|
|
||||||
*/
|
|
||||||
String getDescription (const String& returnValueForZeroTime = "0") const;
|
|
||||||
std::string to_string () const;
|
|
||||||
|
|
||||||
template <typename Number>
|
template <typename Number>
|
||||||
RelativeTime operator+ (Number seconds) const noexcept
|
RelativeTime operator+ (Number seconds) const noexcept
|
||||||
{ return RelativeTime (numSeconds + seconds); }
|
{ return RelativeTime (numSeconds + seconds); }
|
||||||
@@ -204,12 +185,6 @@ RelativeTime operator+ (RelativeTime t1, RelativeTime t2) noexcept;
|
|||||||
/** Subtracts two RelativeTimes. */
|
/** Subtracts two RelativeTimes. */
|
||||||
RelativeTime operator- (RelativeTime t1, RelativeTime t2) noexcept;
|
RelativeTime operator- (RelativeTime t1, RelativeTime t2) noexcept;
|
||||||
|
|
||||||
inline std::ostream& operator<< (std::ostream& os, RelativeTime const& diff)
|
|
||||||
{
|
|
||||||
os << diff.to_string();
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ public:
|
|||||||
for (auto iter : workers_)
|
for (auto iter : workers_)
|
||||||
iter->sample();
|
iter->sample();
|
||||||
|
|
||||||
|
using namespace std::chrono;
|
||||||
clock_type::time_point const when (
|
clock_type::time_point const when (
|
||||||
floor <seconds> (
|
floor <seconds> (
|
||||||
clock_type::now().time_since_epoch()) +
|
clock_type::now().time_since_epoch()) +
|
||||||
|
|||||||
@@ -1,803 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
// chrono_io
|
|
||||||
//
|
|
||||||
// (C) Copyright Howard Hinnant
|
|
||||||
// Use, modification and distribution are subject to the Boost Software License,
|
|
||||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
// http://www.boost.org/LICENSE_1_0.txt).
|
|
||||||
|
|
||||||
#ifndef BEAST_CHRONO_CHRONO_IO_H_INCLUDED
|
|
||||||
#define BEAST_CHRONO_CHRONO_IO_H_INCLUDED
|
|
||||||
|
|
||||||
#include <beast/Config.h>
|
|
||||||
|
|
||||||
#include <ctime>
|
|
||||||
#include <locale>
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
chrono_io synopsis
|
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
#include <ratio_io>
|
|
||||||
|
|
||||||
namespace std
|
|
||||||
{
|
|
||||||
namespace chrono
|
|
||||||
{
|
|
||||||
|
|
||||||
enum duration_style {prefix, symbol};
|
|
||||||
enum timezone {utc, local};
|
|
||||||
|
|
||||||
// facets
|
|
||||||
|
|
||||||
class durationpunct
|
|
||||||
: public locale::facet
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static locale::id id;
|
|
||||||
|
|
||||||
explicit durationpunct(size_t refs = 0);
|
|
||||||
explicit durationpunct(duration_style fmt, size_t refs = 0);
|
|
||||||
|
|
||||||
bool is_symbol_name() const noexcept;
|
|
||||||
bool is_prefix_name() const noexcept;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class charT>
|
|
||||||
class timepunct
|
|
||||||
: public locale::facet
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef basic_string<charT> string_type;
|
|
||||||
|
|
||||||
static locale::id id;
|
|
||||||
|
|
||||||
explicit timepunct(size_t refs = 0);
|
|
||||||
timepunct(timezone tz, string_type fmt, size_t refs = 0);
|
|
||||||
|
|
||||||
const string_type& fmt() const noexcept;
|
|
||||||
std::chrono::timezone timezone() const noexcept;
|
|
||||||
};
|
|
||||||
|
|
||||||
// manipulators
|
|
||||||
|
|
||||||
class duration_fmt
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit duration_fmt(duration_style f) noexcept;
|
|
||||||
explicit operator duration_style() const noexcept;
|
|
||||||
};
|
|
||||||
|
|
||||||
unspecified time_fmt(timezone tz);
|
|
||||||
template<class charT>
|
|
||||||
unspecified time_fmt(timezone tz, basic_string<charT> fmt);
|
|
||||||
template<class charT>
|
|
||||||
unspecified time_fmt(timezone tz, const charT* fmt);
|
|
||||||
|
|
||||||
template<class charT, class traits>
|
|
||||||
std::basic_ostream<charT, traits>&
|
|
||||||
operator<<(std::basic_ostream<charT, traits>& os, duration_fmt d);
|
|
||||||
|
|
||||||
template<class charT, class traits>
|
|
||||||
std::basic_istream<charT, traits>&
|
|
||||||
operator>>(std::basic_istream<charT, traits>& is, duration_fmt d);
|
|
||||||
|
|
||||||
// duration I/O
|
|
||||||
|
|
||||||
template <class charT, class Traits, class Rep, class Period>
|
|
||||||
basic_ostream<charT, Traits>&
|
|
||||||
operator<<(basic_ostream<charT, Traits>& os, const duration<Rep, Period>& d);
|
|
||||||
|
|
||||||
template <class charT, class Traits, class Rep, class Period>
|
|
||||||
basic_istream<charT, Traits>&
|
|
||||||
operator>>(basic_istream<charT, Traits>& is, duration<Rep, Period>& d);
|
|
||||||
|
|
||||||
// system_clock I/O
|
|
||||||
|
|
||||||
template <class charT, class Traits, class Duration>
|
|
||||||
basic_ostream<charT, Traits>&
|
|
||||||
operator<<(basic_ostream<charT, Traits>& os,
|
|
||||||
const time_point<system_clock, Duration>& tp);
|
|
||||||
|
|
||||||
template <class charT, class Traits, class Duration>
|
|
||||||
basic_istream<charT, Traits>&
|
|
||||||
operator>>(basic_istream<charT, Traits>& is,
|
|
||||||
time_point<system_clock, Duration>& tp);
|
|
||||||
|
|
||||||
// steady_clock I/O
|
|
||||||
|
|
||||||
template <class charT, class Traits, class Duration>
|
|
||||||
basic_ostream<charT, Traits>&
|
|
||||||
operator<<(basic_ostream<charT, Traits>& os,
|
|
||||||
const time_point<steady_clock, Duration>& tp);
|
|
||||||
|
|
||||||
template <class charT, class Traits, class Duration>
|
|
||||||
basic_istream<charT, Traits>&
|
|
||||||
operator>>(basic_istream<charT, Traits>& is,
|
|
||||||
time_point<steady_clock, Duration>& tp);
|
|
||||||
|
|
||||||
// high_resolution_clock I/O
|
|
||||||
|
|
||||||
template <class charT, class Traits, class Duration>
|
|
||||||
basic_ostream<charT, Traits>&
|
|
||||||
operator<<(basic_ostream<charT, Traits>& os,
|
|
||||||
const time_point<high_resolution_clock, Duration>& tp);
|
|
||||||
|
|
||||||
template <class charT, class Traits, class Duration>
|
|
||||||
basic_istream<charT, Traits>&
|
|
||||||
operator>>(basic_istream<charT, Traits>& is,
|
|
||||||
time_point<high_resolution_clock, Duration>& tp);
|
|
||||||
|
|
||||||
} // chrono
|
|
||||||
} // std
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
#include <beast/chrono/ratio_io.h>
|
|
||||||
|
|
||||||
//_LIBCPP_BEGIN_NAMESPACE_STD
|
|
||||||
namespace std {
|
|
||||||
|
|
||||||
namespace chrono
|
|
||||||
{
|
|
||||||
|
|
||||||
template <class To, class Rep, class Period>
|
|
||||||
To
|
|
||||||
round(const duration<Rep, Period>& d)
|
|
||||||
{
|
|
||||||
To t0 = duration_cast<To>(d);
|
|
||||||
To t1 = t0;
|
|
||||||
++t1;
|
|
||||||
typedef typename common_type<To, duration<Rep, Period> >::type _D;
|
|
||||||
_D diff0 = d - t0;
|
|
||||||
_D diff1 = t1 - d;
|
|
||||||
if (diff0 == diff1)
|
|
||||||
{
|
|
||||||
if (t0.count() & 1)
|
|
||||||
return t1;
|
|
||||||
return t0;
|
|
||||||
}
|
|
||||||
else if (diff0 < diff1)
|
|
||||||
return t0;
|
|
||||||
return t1;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum duration_style {prefix, symbol};
|
|
||||||
enum timezone {utc, local};
|
|
||||||
|
|
||||||
class durationpunct
|
|
||||||
: public locale::facet
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
duration_style __style_;
|
|
||||||
public:
|
|
||||||
static locale::id id;
|
|
||||||
|
|
||||||
explicit durationpunct(size_t refs = 0)
|
|
||||||
: locale::facet(refs), __style_(prefix) {}
|
|
||||||
|
|
||||||
explicit durationpunct(duration_style fmt, size_t refs = 0)
|
|
||||||
: locale::facet(refs), __style_(fmt) {}
|
|
||||||
|
|
||||||
bool is_symbol_name() const noexcept {return __style_ == symbol;}
|
|
||||||
bool is_prefix_name() const noexcept {return __style_ == prefix;}
|
|
||||||
};
|
|
||||||
|
|
||||||
class duration_fmt
|
|
||||||
{
|
|
||||||
duration_style form_;
|
|
||||||
public:
|
|
||||||
explicit duration_fmt(duration_style f) noexcept : form_(f) {}
|
|
||||||
// VFALCO NOTE disabled this for MSVC
|
|
||||||
/*explicit*/
|
|
||||||
operator duration_style() const noexcept {return form_;}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class charT, class traits>
|
|
||||||
basic_ostream<charT, traits>&
|
|
||||||
operator <<(basic_ostream<charT, traits>& os, duration_fmt d)
|
|
||||||
{
|
|
||||||
os.imbue(locale(os.getloc(), new durationpunct(static_cast<duration_style>(d))));
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class charT, class traits>
|
|
||||||
basic_istream<charT, traits>&
|
|
||||||
operator >>(basic_istream<charT, traits>& is, duration_fmt d)
|
|
||||||
{
|
|
||||||
is.imbue(locale(is.getloc(), new durationpunct(static_cast<duration_style>(d))));
|
|
||||||
return is;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _CharT, class _Rep, class _Period>
|
|
||||||
basic_string<_CharT>
|
|
||||||
__get_unit(bool __is_long, const duration<_Rep, _Period>& d)
|
|
||||||
{
|
|
||||||
if (__is_long)
|
|
||||||
{
|
|
||||||
_CharT __p[] = {'s', 'e', 'c', 'o', 'n', 'd', 's', 0};
|
|
||||||
basic_string<_CharT> s = ratio_string<_Period, _CharT>::prefix() + __p;
|
|
||||||
if (d.count() == 1 || d.count() == -1)
|
|
||||||
s.pop_back();
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
return ratio_string<_Period, _CharT>::symbol() + 's';
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _CharT, class _Rep>
|
|
||||||
basic_string<_CharT>
|
|
||||||
__get_unit(bool __is_long, const duration<_Rep, ratio<1> >& d)
|
|
||||||
{
|
|
||||||
if (__is_long)
|
|
||||||
{
|
|
||||||
_CharT __p[] = {'s', 'e', 'c', 'o', 'n', 'd', 's'};
|
|
||||||
basic_string<_CharT> s = basic_string<_CharT>(__p, __p + sizeof(__p) / sizeof(_CharT));
|
|
||||||
if (d.count() == 1 || d.count() == -1)
|
|
||||||
s.pop_back();
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
return basic_string<_CharT>(1, 's');
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _CharT, class _Rep>
|
|
||||||
basic_string<_CharT>
|
|
||||||
__get_unit(bool __is_long, const duration<_Rep, ratio<60> >& d)
|
|
||||||
{
|
|
||||||
if (__is_long)
|
|
||||||
{
|
|
||||||
_CharT __p[] = {'m', 'i', 'n', 'u', 't', 'e', 's'};
|
|
||||||
basic_string<_CharT> s = basic_string<_CharT>(__p, __p + sizeof(__p) / sizeof(_CharT));
|
|
||||||
if (d.count() == 1 || d.count() == -1)
|
|
||||||
s.pop_back();
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
_CharT __p[] = {'m', 'i', 'n'};
|
|
||||||
return basic_string<_CharT>(__p, __p + sizeof(__p) / sizeof(_CharT));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _CharT, class _Rep>
|
|
||||||
basic_string<_CharT>
|
|
||||||
__get_unit(bool __is_long, const duration<_Rep, ratio<3600> >& d)
|
|
||||||
{
|
|
||||||
if (__is_long)
|
|
||||||
{
|
|
||||||
_CharT __p[] = {'h', 'o', 'u', 'r', 's'};
|
|
||||||
basic_string<_CharT> s = basic_string<_CharT>(__p, __p + sizeof(__p) / sizeof(_CharT));
|
|
||||||
if (d.count() == 1 || d.count() == -1)
|
|
||||||
s.pop_back();
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
return basic_string<_CharT>(1, 'h');
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _CharT, class _Traits, class _Rep, class _Period>
|
|
||||||
basic_ostream<_CharT, _Traits>&
|
|
||||||
operator<<(basic_ostream<_CharT, _Traits>& __os, const duration<_Rep, _Period>& __d)
|
|
||||||
{
|
|
||||||
typename basic_ostream<_CharT, _Traits>::sentry ok(__os);
|
|
||||||
if (ok)
|
|
||||||
{
|
|
||||||
typedef durationpunct _F;
|
|
||||||
typedef basic_string<_CharT> string_type;
|
|
||||||
bool failed = false;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
bool __is_long = true;
|
|
||||||
locale __loc = __os.getloc();
|
|
||||||
if (has_facet<_F>(__loc))
|
|
||||||
{
|
|
||||||
const _F& f = use_facet<_F>(__loc);
|
|
||||||
__is_long = f.is_prefix_name();
|
|
||||||
}
|
|
||||||
string_type __unit = __get_unit<_CharT>(__is_long, __d);
|
|
||||||
__os << __d.count() << ' ' << __unit;
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
failed = true;
|
|
||||||
}
|
|
||||||
if (failed)
|
|
||||||
__os.setstate(ios_base::failbit | ios_base::badbit);
|
|
||||||
}
|
|
||||||
return __os;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _Rep, bool = is_scalar<_Rep>::value>
|
|
||||||
struct __duration_io_intermediate
|
|
||||||
{
|
|
||||||
typedef _Rep type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class _Rep>
|
|
||||||
struct __duration_io_intermediate<_Rep, true>
|
|
||||||
{
|
|
||||||
typedef typename conditional
|
|
||||||
<
|
|
||||||
is_floating_point<_Rep>::value,
|
|
||||||
long double,
|
|
||||||
typename conditional
|
|
||||||
<
|
|
||||||
is_signed<_Rep>::value,
|
|
||||||
long long,
|
|
||||||
unsigned long long
|
|
||||||
>::type
|
|
||||||
>::type type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
T
|
|
||||||
__gcd(T x, T y)
|
|
||||||
{
|
|
||||||
while (y != 0)
|
|
||||||
{
|
|
||||||
T old_x = x;
|
|
||||||
x = y;
|
|
||||||
y = old_x % y;
|
|
||||||
}
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
long double
|
|
||||||
inline
|
|
||||||
__gcd(long double, long double)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _CharT, class _Traits, class _Rep, class _Period>
|
|
||||||
basic_istream<_CharT, _Traits>&
|
|
||||||
operator>>(basic_istream<_CharT, _Traits>& __is, duration<_Rep, _Period>& __d)
|
|
||||||
{
|
|
||||||
// These are unused and generate warnings
|
|
||||||
//typedef basic_string<_CharT> string_type;
|
|
||||||
//typedef durationpunct _F;
|
|
||||||
|
|
||||||
typedef typename __duration_io_intermediate<_Rep>::type _IR;
|
|
||||||
_IR __r;
|
|
||||||
// read value into __r
|
|
||||||
__is >> __r;
|
|
||||||
if (__is.good())
|
|
||||||
{
|
|
||||||
// now determine unit
|
|
||||||
typedef istreambuf_iterator<_CharT, _Traits> _I;
|
|
||||||
_I __i(__is);
|
|
||||||
_I __e;
|
|
||||||
if (__i != __e && *__i == ' ') // mandatory ' ' after value
|
|
||||||
{
|
|
||||||
++__i;
|
|
||||||
if (__i != __e)
|
|
||||||
{
|
|
||||||
locale __loc = __is.getloc();
|
|
||||||
// unit is num / den (yet to be determined)
|
|
||||||
unsigned long long num = 0;
|
|
||||||
unsigned long long den = 0;
|
|
||||||
ios_base::iostate __err = ios_base::goodbit;
|
|
||||||
if (*__i == '[')
|
|
||||||
{
|
|
||||||
// parse [N/D]s or [N/D]seconds format
|
|
||||||
++__i;
|
|
||||||
_CharT __x;
|
|
||||||
__is >> num >> __x >> den;
|
|
||||||
if (!__is.good() || __x != '/')
|
|
||||||
{
|
|
||||||
__is.setstate(__is.failbit);
|
|
||||||
return __is;
|
|
||||||
}
|
|
||||||
__i = _I(__is);
|
|
||||||
if (*__i != ']')
|
|
||||||
{
|
|
||||||
__is.setstate(__is.failbit);
|
|
||||||
return __is;
|
|
||||||
}
|
|
||||||
++__i;
|
|
||||||
const basic_string<_CharT> __units[] =
|
|
||||||
{
|
|
||||||
__get_unit<_CharT>(true, seconds(2)),
|
|
||||||
__get_unit<_CharT>(true, seconds(1)),
|
|
||||||
__get_unit<_CharT>(false, seconds(1))
|
|
||||||
};
|
|
||||||
const basic_string<_CharT>* __k = __scan_keyword(__i, __e,
|
|
||||||
__units, __units + sizeof(__units)/sizeof(__units[0]),
|
|
||||||
use_facet<ctype<_CharT> >(__loc),
|
|
||||||
__err);
|
|
||||||
switch ((__k - __units) / 3)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
__is.setstate(__err);
|
|
||||||
return __is;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// parse SI name, short or long
|
|
||||||
const basic_string<_CharT> __units[] =
|
|
||||||
{
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, atto>(2)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, atto>(1)),
|
|
||||||
__get_unit<_CharT>(false, duration<_Rep, atto>(1)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, femto>(2)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, femto>(1)),
|
|
||||||
__get_unit<_CharT>(false, duration<_Rep, femto>(1)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, pico>(2)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, pico>(1)),
|
|
||||||
__get_unit<_CharT>(false, duration<_Rep, pico>(1)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, nano>(2)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, nano>(1)),
|
|
||||||
__get_unit<_CharT>(false, duration<_Rep, nano>(1)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, micro>(2)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, micro>(1)),
|
|
||||||
__get_unit<_CharT>(false, duration<_Rep, micro>(1)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, milli>(2)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, milli>(1)),
|
|
||||||
__get_unit<_CharT>(false, duration<_Rep, milli>(1)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, centi>(2)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, centi>(1)),
|
|
||||||
__get_unit<_CharT>(false, duration<_Rep, centi>(1)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, deci>(2)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, deci>(1)),
|
|
||||||
__get_unit<_CharT>(false, duration<_Rep, deci>(1)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, deca>(2)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, deca>(1)),
|
|
||||||
__get_unit<_CharT>(false, duration<_Rep, deca>(1)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, hecto>(2)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, hecto>(1)),
|
|
||||||
__get_unit<_CharT>(false, duration<_Rep, hecto>(1)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, kilo>(2)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, kilo>(1)),
|
|
||||||
__get_unit<_CharT>(false, duration<_Rep, kilo>(1)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, mega>(2)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, mega>(1)),
|
|
||||||
__get_unit<_CharT>(false, duration<_Rep, mega>(1)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, giga>(2)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, giga>(1)),
|
|
||||||
__get_unit<_CharT>(false, duration<_Rep, giga>(1)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, tera>(2)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, tera>(1)),
|
|
||||||
__get_unit<_CharT>(false, duration<_Rep, tera>(1)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, peta>(2)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, peta>(1)),
|
|
||||||
__get_unit<_CharT>(false, duration<_Rep, peta>(1)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, exa>(2)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, exa>(1)),
|
|
||||||
__get_unit<_CharT>(false, duration<_Rep, exa>(1)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, ratio<1> >(2)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, ratio<1> >(1)),
|
|
||||||
__get_unit<_CharT>(false, duration<_Rep, ratio<1> >(1)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, ratio<60> >(2)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, ratio<60> >(1)),
|
|
||||||
__get_unit<_CharT>(false, duration<_Rep, ratio<60> >(1)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, ratio<3600> >(2)),
|
|
||||||
__get_unit<_CharT>(true, duration<_Rep, ratio<3600> >(1)),
|
|
||||||
__get_unit<_CharT>(false, duration<_Rep, ratio<3600> >(1))
|
|
||||||
};
|
|
||||||
const basic_string<_CharT>* __k = __scan_keyword(__i, __e,
|
|
||||||
__units, __units + sizeof(__units)/sizeof(__units[0]),
|
|
||||||
use_facet<ctype<_CharT> >(__loc),
|
|
||||||
__err);
|
|
||||||
switch (__k - __units)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
case 1:
|
|
||||||
case 2:
|
|
||||||
num = 1ULL;
|
|
||||||
den = 1000000000000000000ULL;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
case 4:
|
|
||||||
case 5:
|
|
||||||
num = 1ULL;
|
|
||||||
den = 1000000000000000ULL;
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
case 7:
|
|
||||||
case 8:
|
|
||||||
num = 1ULL;
|
|
||||||
den = 1000000000000ULL;
|
|
||||||
break;
|
|
||||||
case 9:
|
|
||||||
case 10:
|
|
||||||
case 11:
|
|
||||||
num = 1ULL;
|
|
||||||
den = 1000000000ULL;
|
|
||||||
break;
|
|
||||||
case 12:
|
|
||||||
case 13:
|
|
||||||
case 14:
|
|
||||||
num = 1ULL;
|
|
||||||
den = 1000000ULL;
|
|
||||||
break;
|
|
||||||
case 15:
|
|
||||||
case 16:
|
|
||||||
case 17:
|
|
||||||
num = 1ULL;
|
|
||||||
den = 1000ULL;
|
|
||||||
break;
|
|
||||||
case 18:
|
|
||||||
case 19:
|
|
||||||
case 20:
|
|
||||||
num = 1ULL;
|
|
||||||
den = 100ULL;
|
|
||||||
break;
|
|
||||||
case 21:
|
|
||||||
case 22:
|
|
||||||
case 23:
|
|
||||||
num = 1ULL;
|
|
||||||
den = 10ULL;
|
|
||||||
break;
|
|
||||||
case 24:
|
|
||||||
case 25:
|
|
||||||
case 26:
|
|
||||||
num = 10ULL;
|
|
||||||
den = 1ULL;
|
|
||||||
break;
|
|
||||||
case 27:
|
|
||||||
case 28:
|
|
||||||
case 29:
|
|
||||||
num = 100ULL;
|
|
||||||
den = 1ULL;
|
|
||||||
break;
|
|
||||||
case 30:
|
|
||||||
case 31:
|
|
||||||
case 32:
|
|
||||||
num = 1000ULL;
|
|
||||||
den = 1ULL;
|
|
||||||
break;
|
|
||||||
case 33:
|
|
||||||
case 34:
|
|
||||||
case 35:
|
|
||||||
num = 1000000ULL;
|
|
||||||
den = 1ULL;
|
|
||||||
break;
|
|
||||||
case 36:
|
|
||||||
case 37:
|
|
||||||
case 38:
|
|
||||||
num = 1000000000ULL;
|
|
||||||
den = 1ULL;
|
|
||||||
break;
|
|
||||||
case 39:
|
|
||||||
case 40:
|
|
||||||
case 41:
|
|
||||||
num = 1000000000000ULL;
|
|
||||||
den = 1ULL;
|
|
||||||
break;
|
|
||||||
case 42:
|
|
||||||
case 43:
|
|
||||||
case 44:
|
|
||||||
num = 1000000000000000ULL;
|
|
||||||
den = 1ULL;
|
|
||||||
break;
|
|
||||||
case 45:
|
|
||||||
case 46:
|
|
||||||
case 47:
|
|
||||||
num = 1000000000000000000ULL;
|
|
||||||
den = 1ULL;
|
|
||||||
break;
|
|
||||||
case 48:
|
|
||||||
case 49:
|
|
||||||
case 50:
|
|
||||||
num = 1;
|
|
||||||
den = 1;
|
|
||||||
break;
|
|
||||||
case 51:
|
|
||||||
case 52:
|
|
||||||
case 53:
|
|
||||||
num = 60;
|
|
||||||
den = 1;
|
|
||||||
break;
|
|
||||||
case 54:
|
|
||||||
case 55:
|
|
||||||
case 56:
|
|
||||||
num = 3600;
|
|
||||||
den = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
__is.setstate(__err);
|
|
||||||
return __is;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// unit is num/den
|
|
||||||
// __r should be multiplied by (num/den) / _Period
|
|
||||||
// Reduce (num/den) / _Period to lowest terms
|
|
||||||
unsigned long long __gcd_n1_n2 = __gcd<unsigned long long>(num, _Period::num);
|
|
||||||
unsigned long long __gcd_d1_d2 = __gcd<unsigned long long>(den, _Period::den);
|
|
||||||
num /= __gcd_n1_n2;
|
|
||||||
den /= __gcd_d1_d2;
|
|
||||||
unsigned long long __n2 = _Period::num / __gcd_n1_n2;
|
|
||||||
unsigned long long __d2 = _Period::den / __gcd_d1_d2;
|
|
||||||
if (num > numeric_limits<unsigned long long>::max() / __d2 ||
|
|
||||||
den > numeric_limits<unsigned long long>::max() / __n2)
|
|
||||||
{
|
|
||||||
// (num/den) / _Period overflows
|
|
||||||
__is.setstate(__is.failbit);
|
|
||||||
return __is;
|
|
||||||
}
|
|
||||||
num *= __d2;
|
|
||||||
den *= __n2;
|
|
||||||
// num / den is now factor to multiply by __r
|
|
||||||
typedef typename common_type<_IR, unsigned long long>::type _CT;
|
|
||||||
if (is_integral<_IR>::value)
|
|
||||||
{
|
|
||||||
// Reduce __r * num / den
|
|
||||||
_CT __t = __gcd<_CT>(__r, den);
|
|
||||||
__r /= __t;
|
|
||||||
den /= __t;
|
|
||||||
if (den != 1)
|
|
||||||
{
|
|
||||||
// Conversion to _Period is integral and not exact
|
|
||||||
__is.setstate(__is.failbit);
|
|
||||||
return __is;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (__r > duration_values<_CT>::max() / num)
|
|
||||||
{
|
|
||||||
// Conversion to _Period overflowed
|
|
||||||
__is.setstate(__is.failbit);
|
|
||||||
return __is;
|
|
||||||
}
|
|
||||||
_CT __t = __r * num;
|
|
||||||
__t /= den;
|
|
||||||
if (duration_values<_Rep>::max() < __t)
|
|
||||||
{
|
|
||||||
// Conversion to _Period overflowed
|
|
||||||
__is.setstate(__is.failbit);
|
|
||||||
return __is;
|
|
||||||
}
|
|
||||||
// Success! Store it.
|
|
||||||
__r = _Rep(__t);
|
|
||||||
__d = duration<_Rep, _Period>(__r);
|
|
||||||
__is.setstate(__err);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
__is.setstate(__is.failbit | __is.eofbit);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (__i == __e)
|
|
||||||
__is.setstate(__is.eofbit);
|
|
||||||
__is.setstate(__is.failbit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
__is.setstate(__is.failbit);
|
|
||||||
return __is;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class charT>
|
|
||||||
class timepunct
|
|
||||||
: public locale::facet
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef basic_string<charT> string_type;
|
|
||||||
|
|
||||||
private:
|
|
||||||
string_type fmt_;
|
|
||||||
chrono::timezone tz_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static locale::id id;
|
|
||||||
|
|
||||||
explicit timepunct(size_t refs = 0)
|
|
||||||
: locale::facet(refs), tz_(utc) {}
|
|
||||||
timepunct(timezone tz, string_type fmt, size_t refs = 0)
|
|
||||||
: locale::facet(refs), fmt_(std::move(fmt)), tz_(tz) {}
|
|
||||||
|
|
||||||
const string_type& fmt() const noexcept {return fmt_;}
|
|
||||||
chrono::timezone get_timezone() const noexcept {return tz_;}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class CharT>
|
|
||||||
locale::id
|
|
||||||
timepunct<CharT>::id;
|
|
||||||
|
|
||||||
template <class _CharT, class _Traits, class _Duration>
|
|
||||||
basic_ostream<_CharT, _Traits>&
|
|
||||||
operator<<(basic_ostream<_CharT, _Traits>& __os,
|
|
||||||
const time_point<steady_clock, _Duration>& __tp)
|
|
||||||
{
|
|
||||||
return __os << __tp.time_since_epoch() << " since boot";
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class charT>
|
|
||||||
struct __time_manip
|
|
||||||
{
|
|
||||||
basic_string<charT> fmt_;
|
|
||||||
timezone tz_;
|
|
||||||
|
|
||||||
__time_manip(timezone tz, basic_string<charT> fmt)
|
|
||||||
: fmt_(std::move(fmt)),
|
|
||||||
tz_(tz) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class charT, class traits>
|
|
||||||
basic_ostream<charT, traits>&
|
|
||||||
operator <<(basic_ostream<charT, traits>& os, __time_manip<charT> m)
|
|
||||||
{
|
|
||||||
os.imbue(locale(os.getloc(), new timepunct<charT>(m.tz_, std::move(m.fmt_))));
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class charT, class traits>
|
|
||||||
basic_istream<charT, traits>&
|
|
||||||
operator >>(basic_istream<charT, traits>& is, __time_manip<charT> m)
|
|
||||||
{
|
|
||||||
is.imbue(locale(is.getloc(), new timepunct<charT>(m.tz_, std::move(m.fmt_))));
|
|
||||||
return is;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class charT>
|
|
||||||
inline
|
|
||||||
__time_manip<charT>
|
|
||||||
time_fmt(timezone tz, const charT* fmt)
|
|
||||||
{
|
|
||||||
return __time_manip<charT>(tz, fmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class charT>
|
|
||||||
inline
|
|
||||||
__time_manip<charT>
|
|
||||||
time_fmt(timezone tz, basic_string<charT> fmt)
|
|
||||||
{
|
|
||||||
return __time_manip<charT>(tz, std::move(fmt));
|
|
||||||
}
|
|
||||||
|
|
||||||
class __time_man
|
|
||||||
{
|
|
||||||
timezone form_;
|
|
||||||
public:
|
|
||||||
explicit __time_man(timezone f) : form_(f) {}
|
|
||||||
// explicit
|
|
||||||
operator timezone() const {return form_;}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class charT, class traits>
|
|
||||||
basic_ostream<charT, traits>&
|
|
||||||
operator <<(basic_ostream<charT, traits>& os, __time_man m)
|
|
||||||
{
|
|
||||||
os.imbue(locale(os.getloc(), new timepunct<charT>(static_cast<timezone>(m), basic_string<charT>())));
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class charT, class traits>
|
|
||||||
basic_istream<charT, traits>&
|
|
||||||
operator >>(basic_istream<charT, traits>& is, __time_man m)
|
|
||||||
{
|
|
||||||
is.imbue(locale(is.getloc(), new timepunct<charT>(static_cast<timezone>(m), basic_string<charT>())));
|
|
||||||
return is;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
|
||||||
__time_man
|
|
||||||
time_fmt(timezone f)
|
|
||||||
{
|
|
||||||
return __time_man(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // chrono
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -23,6 +23,7 @@
|
|||||||
// From Howard Hinnant
|
// From Howard Hinnant
|
||||||
// http://home.roadrunner.com/~hinnant/duration_io/chrono_util.html
|
// http://home.roadrunner.com/~hinnant/duration_io/chrono_util.html
|
||||||
|
|
||||||
|
#if !defined(_MSC_FULL_VER) || (_MSC_FULL_VER <= 190023506)
|
||||||
// round down
|
// round down
|
||||||
template <class To, class Rep, class Period>
|
template <class To, class Rep, class Period>
|
||||||
To floor(std::chrono::duration <Rep, Period> const& d)
|
To floor(std::chrono::duration <Rep, Period> const& d)
|
||||||
@@ -62,5 +63,6 @@ To ceil (std::chrono::duration <Rep, Period> const& d)
|
|||||||
++t;
|
++t;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -23,16 +23,6 @@
|
|||||||
|
|
||||||
#include <beast/chrono/RelativeTime.h>
|
#include <beast/chrono/RelativeTime.h>
|
||||||
|
|
||||||
// VFALCO TODO Migrate the localizable strings interfaces for this file
|
|
||||||
|
|
||||||
#ifndef NEEDS_TRANS
|
|
||||||
#define NEEDS_TRANS(s) (s)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef TRANS
|
|
||||||
#define TRANS(s) (s)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
RelativeTime::RelativeTime (const RelativeTime::value_type secs) noexcept
|
RelativeTime::RelativeTime (const RelativeTime::value_type secs) noexcept
|
||||||
@@ -175,86 +165,6 @@ bool operator<= (RelativeTime t1, RelativeTime t2) noexcept
|
|||||||
return t1.inSeconds() <= t2.inSeconds();
|
return t1.inSeconds() <= t2.inSeconds();
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
static void translateTimeField (String& result, int n, const char* singular, const char* plural)
|
|
||||||
{
|
|
||||||
result << TRANS (String((n == 1) ? singular : plural))
|
|
||||||
.replace (n == 1 ? "1" : "2", String (n))
|
|
||||||
<< ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
String RelativeTime::getDescription (const String& returnValueForZeroTime) const
|
|
||||||
{
|
|
||||||
if (numSeconds < 0.001 && numSeconds > -0.001)
|
|
||||||
return returnValueForZeroTime;
|
|
||||||
|
|
||||||
String result;
|
|
||||||
result.preallocateBytes (32);
|
|
||||||
|
|
||||||
if (numSeconds < 0)
|
|
||||||
result << '-';
|
|
||||||
|
|
||||||
int fieldsShown = 0;
|
|
||||||
int n = std::abs ((int) inWeeks());
|
|
||||||
if (n > 0)
|
|
||||||
{
|
|
||||||
translateTimeField (result, n, NEEDS_TRANS("1 week"), NEEDS_TRANS("2 weeks"));
|
|
||||||
++fieldsShown;
|
|
||||||
}
|
|
||||||
|
|
||||||
n = std::abs ((int) inDays()) % 7;
|
|
||||||
if (n > 0)
|
|
||||||
{
|
|
||||||
translateTimeField (result, n, NEEDS_TRANS("1 day"), NEEDS_TRANS("2 days"));
|
|
||||||
++fieldsShown;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fieldsShown < 2)
|
|
||||||
{
|
|
||||||
n = std::abs ((int) inHours()) % 24;
|
|
||||||
if (n > 0)
|
|
||||||
{
|
|
||||||
translateTimeField (result, n, NEEDS_TRANS("1 hour"), NEEDS_TRANS("2 hours"));
|
|
||||||
++fieldsShown;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fieldsShown < 2)
|
|
||||||
{
|
|
||||||
n = std::abs ((int) inMinutes()) % 60;
|
|
||||||
if (n > 0)
|
|
||||||
{
|
|
||||||
translateTimeField (result, n, NEEDS_TRANS("1 minute"), NEEDS_TRANS("2 minutes"));
|
|
||||||
++fieldsShown;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fieldsShown < 2)
|
|
||||||
{
|
|
||||||
n = std::abs ((int) inSeconds()) % 60;
|
|
||||||
if (n > 0)
|
|
||||||
{
|
|
||||||
translateTimeField (result, n, NEEDS_TRANS("1 seconds"), NEEDS_TRANS("2 seconds"));
|
|
||||||
++fieldsShown;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fieldsShown == 0)
|
|
||||||
{
|
|
||||||
n = std::abs ((int) inMilliseconds()) % 1000;
|
|
||||||
if (n > 0)
|
|
||||||
result << n << ' ' << TRANS ("ms");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.trimEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string RelativeTime::to_string () const
|
|
||||||
{
|
|
||||||
return getDescription ().toStdString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if BEAST_WINDOWS
|
#if BEAST_WINDOWS
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
// chrono_io
|
|
||||||
//
|
|
||||||
// (C) Copyright Howard Hinnant
|
|
||||||
// Use, modification and distribution are subject to the Boost Software License,
|
|
||||||
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
// http://www.boost.org/LICENSE_1_0.txt).
|
|
||||||
|
|
||||||
#include <beast/chrono/chrono_io.h>
|
|
||||||
|
|
||||||
//_LIBCPP_BEGIN_NAMESPACE_STD
|
|
||||||
namespace std {
|
|
||||||
|
|
||||||
namespace chrono
|
|
||||||
{
|
|
||||||
|
|
||||||
locale::id
|
|
||||||
durationpunct::id;
|
|
||||||
|
|
||||||
} // chrono
|
|
||||||
|
|
||||||
//_LIBCPP_END_NAMESPACE_STD
|
|
||||||
}
|
|
||||||
@@ -42,9 +42,9 @@ public:
|
|||||||
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss <<
|
ss <<
|
||||||
"t1= " << t1.time_since_epoch() <<
|
"t1= " << t1.time_since_epoch().count() <<
|
||||||
", t2= " << t2.time_since_epoch() <<
|
", t2= " << t2.time_since_epoch().count() <<
|
||||||
", elapsed= " << (t2 - t1);
|
", elapsed= " << (t2 - t1).count();
|
||||||
log << ss.str();
|
log << ss.str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -56,13 +56,13 @@ public:
|
|||||||
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
ss << "now() = " << c.now().time_since_epoch() << std::endl;
|
ss << "now() = " << c.now().time_since_epoch().count() << std::endl;
|
||||||
|
|
||||||
c.set (clock_type::time_point (std::chrono::seconds(1)));
|
c.set (clock_type::time_point (std::chrono::seconds(1)));
|
||||||
ss << "now() = " << c.now().time_since_epoch() << std::endl;
|
ss << "now() = " << c.now().time_since_epoch().count() << std::endl;
|
||||||
|
|
||||||
c.set (clock_type::time_point (std::chrono::seconds(2)));
|
c.set (clock_type::time_point (std::chrono::seconds(2)));
|
||||||
ss << "now() = " << c.now().time_since_epoch() << std::endl;
|
ss << "now() = " << c.now().time_since_epoch().count() << std::endl;
|
||||||
|
|
||||||
log << ss.str();
|
log << ss.str();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,107 +50,6 @@
|
|||||||
# define BEAST_CONSTEXPR constexpr
|
# define BEAST_CONSTEXPR constexpr
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Debugging and assertion macros
|
|
||||||
|
|
||||||
#if BEAST_LOG_ASSERTIONS || BEAST_DEBUG
|
|
||||||
#define beast_LogCurrentAssertion beast::logAssertion (__FILE__, __LINE__);
|
|
||||||
#else
|
|
||||||
#define beast_LogCurrentAssertion
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if BEAST_IOS || BEAST_LINUX || BEAST_ANDROID || BEAST_PPC
|
|
||||||
/** This will try to break into the debugger if the app is currently being debugged.
|
|
||||||
If called by an app that's not being debugged, the behaiour isn't defined - it may crash or not, depending
|
|
||||||
on the platform.
|
|
||||||
@see bassert()
|
|
||||||
*/
|
|
||||||
# define beast_breakDebugger { ::kill (0, SIGTRAP); }
|
|
||||||
#elif BEAST_USE_INTRINSICS
|
|
||||||
# ifndef __INTEL_COMPILER
|
|
||||||
# pragma intrinsic (__debugbreak)
|
|
||||||
# endif
|
|
||||||
# define beast_breakDebugger { __debugbreak(); }
|
|
||||||
#elif BEAST_GCC || BEAST_MAC
|
|
||||||
# if BEAST_NO_INLINE_ASM
|
|
||||||
# define beast_breakDebugger { }
|
|
||||||
# else
|
|
||||||
# define beast_breakDebugger { asm ("int $3"); }
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
# define beast_breakDebugger { __asm int 3 }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if BEAST_CLANG && defined (__has_feature) && ! defined (BEAST_ANALYZER_NORETURN)
|
|
||||||
# if __has_feature (attribute_analyzer_noreturn)
|
|
||||||
inline void __attribute__((analyzer_noreturn)) beast_assert_noreturn() {}
|
|
||||||
# define BEAST_ANALYZER_NORETURN beast_assert_noreturn();
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef BEAST_ANALYZER_NORETURN
|
|
||||||
#define BEAST_ANALYZER_NORETURN
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
/** Report a fatal error message and terminate the application.
|
|
||||||
Normally you won't call this directly.
|
|
||||||
*/
|
|
||||||
extern void beast_reportFatalError (char const* message, char const* fileName, int lineNumber);
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if BEAST_DEBUG || DOXYGEN
|
|
||||||
|
|
||||||
/** Writes a string to the standard error stream.
|
|
||||||
This is only compiled in a debug build.
|
|
||||||
*/
|
|
||||||
#define BDBG(dbgtext) { \
|
|
||||||
beast::String tempDbgBuf; \
|
|
||||||
tempDbgBuf << dbgtext; \
|
|
||||||
beast::outputDebugString (tempDbgBuf.toStdString ()); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/** This will always cause an assertion failure.
|
|
||||||
It is only compiled in a debug build, (unless BEAST_LOG_ASSERTIONS is enabled for your build).
|
|
||||||
@see bassert
|
|
||||||
*/
|
|
||||||
#define bassertfalse { beast_LogCurrentAssertion; if (beast::beast_isRunningUnderDebugger()) beast_breakDebugger; BEAST_ANALYZER_NORETURN }
|
|
||||||
|
|
||||||
/** Platform-independent assertion macro.
|
|
||||||
This macro gets turned into a no-op when you're building with debugging turned off, so be
|
|
||||||
careful that the expression you pass to it doesn't perform any actions that are vital for the
|
|
||||||
correct behaviour of your program!
|
|
||||||
@see bassertfalse
|
|
||||||
*/
|
|
||||||
#define bassert(expression) { if (! (expression)) beast_reportFatalError(#expression,__FILE__,__LINE__); }
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define bassertfalse assert(false)
|
|
||||||
#define bassert(expression) assert(expression)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
// If debugging is disabled, these dummy debug and assertion macros are used..
|
|
||||||
|
|
||||||
#define BDBG(dbgtext)
|
|
||||||
#define bassertfalse { beast_LogCurrentAssertion }
|
|
||||||
|
|
||||||
# if BEAST_LOG_ASSERTIONS
|
|
||||||
# define bassert(expression) { if (! (expression)) bassertfalse; }
|
|
||||||
# else
|
|
||||||
# define bassert(a) {}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
#if ! DOXYGEN
|
#if ! DOXYGEN
|
||||||
@@ -195,17 +94,6 @@ extern void beast_reportFatalError (char const* message, char const* fileName, i
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
#if BEAST_ANDROID && ! DOXYGEN
|
|
||||||
# define BEAST_MODAL_LOOPS_PERMITTED 0
|
|
||||||
#elif ! defined (BEAST_MODAL_LOOPS_PERMITTED)
|
|
||||||
/** Some operating environments don't provide a modal loop mechanism, so this
|
|
||||||
flag can be used to disable any functions that try to run a modal loop.
|
|
||||||
*/
|
|
||||||
#define BEAST_MODAL_LOOPS_PERMITTED 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#if BEAST_GCC
|
#if BEAST_GCC
|
||||||
# define BEAST_PACKED __attribute__((packed))
|
# define BEAST_PACKED __attribute__((packed))
|
||||||
#elif ! DOXYGEN
|
#elif ! DOXYGEN
|
||||||
@@ -260,11 +148,4 @@ extern void beast_reportFatalError (char const* message, char const* fileName, i
|
|||||||
# define BEAST_MOVE_CAST(type) type
|
# define BEAST_MOVE_CAST(type) type
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
namespace beast {
|
|
||||||
bool beast_isRunningUnderDebugger();
|
|
||||||
void logAssertion (char const* file, int line);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,86 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_CONFIG_CONTRACTCHECKS_H_INCLUDED
|
|
||||||
#define BEAST_CONFIG_CONTRACTCHECKS_H_INCLUDED
|
|
||||||
|
|
||||||
// This file has to work when included in a C source file.
|
|
||||||
|
|
||||||
#if defined (fatal_error) || \
|
|
||||||
defined (fatal_condition) || \
|
|
||||||
defined (meets_condition) || \
|
|
||||||
defined (meets_precondition) || \
|
|
||||||
defined (meets_postcondition) || \
|
|
||||||
defined (meets_invariant) || \
|
|
||||||
defined (check_invariant)
|
|
||||||
#error "Programming by contract macros cannot be overriden!"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Report a fatal error message and terminate the application.
|
|
||||||
This macro automatically fills in the file and line number
|
|
||||||
Meets this declaration syntax:
|
|
||||||
@code inline void fatal_error (char const* message); @endif
|
|
||||||
@see FatalError
|
|
||||||
*/
|
|
||||||
#define fatal_error(message) beast_reportFatalError (message, __FILE__, __LINE__)
|
|
||||||
|
|
||||||
/** Reports a fatal error message type if the condition is false
|
|
||||||
The condition is always evaluated regardless of settings.
|
|
||||||
Meets this declaration syntax:
|
|
||||||
@code inline void fatal_condition (bool condition, char const* category); @endcode
|
|
||||||
*/
|
|
||||||
#define fatal_condition(condition,category) static_cast <void> \
|
|
||||||
(((!!(condition)) || (beast_reportFatalError ( \
|
|
||||||
category " '" BEAST_STRINGIFY(condition) "' failed.", __FILE__, __LINE__), 0)))
|
|
||||||
|
|
||||||
/** Reports a fatal error message type if the condition is false
|
|
||||||
The condition is always evaluated regardless of settings.
|
|
||||||
Meets this declaration syntax:
|
|
||||||
@code inline void fatal_condition (bool condition, char const* category); @endcode
|
|
||||||
*/
|
|
||||||
#define meets_condition(condition,category) static_cast <bool> \
|
|
||||||
(((!!(condition)) || (beast_reportFatalError ( \
|
|
||||||
category " '" BEAST_STRINGIFY(condition) "' failed.", __FILE__, __LINE__), false)))
|
|
||||||
|
|
||||||
/** Condition tests for programming by contract.
|
|
||||||
The condition is always evaluated regardless of settings, and gets returned.
|
|
||||||
Meets this declaration syntax:
|
|
||||||
@code inline bool meets_condition (bool); @endcode
|
|
||||||
*/
|
|
||||||
/** @{ */
|
|
||||||
#define meets_precondition(condition) meets_condition(condition,"Pre-condition")
|
|
||||||
#define meets_postcondition(condition) meets_condition(condition,"Post-condition")
|
|
||||||
#define meets_invariant(condition) meets_condition(condition,"Invariant")
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
/** Condition tests for programming by contract.
|
|
||||||
The condition is evaluated only if BEAST_DISABLE_CONTRACT_CHECKS is 0.
|
|
||||||
Meets this declaration syntax:
|
|
||||||
@code inline void check_condition (bool); @endcode
|
|
||||||
@see BEAST_DISABLE_CONTRACT_CHECKS
|
|
||||||
*/
|
|
||||||
/** @{ */
|
|
||||||
#if ! BEAST_DISABLE_CONTRACT_CHECKS
|
|
||||||
# define check_invariant(condition) meets_invariant(condition)
|
|
||||||
#else
|
|
||||||
# define check_invariant(condition) ((void)0)
|
|
||||||
#endif
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -199,9 +199,7 @@ private:
|
|||||||
, public std::binary_function <Key, element, bool>
|
, public std::binary_function <Key, element, bool>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
KeyValueCompare ()
|
KeyValueCompare () = default;
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyValueCompare (Compare const& compare)
|
KeyValueCompare (Compare const& compare)
|
||||||
: empty_base_optimization <Compare> (compare)
|
: empty_base_optimization <Compare> (compare)
|
||||||
@@ -234,6 +232,11 @@ private:
|
|||||||
return this->member() (extract (e.value), k);
|
return this->member() (extract (e.value), k);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator() (element const& x, element const& y) const
|
||||||
|
{
|
||||||
|
return this->member() (extract (x.value), extract (y.value));
|
||||||
|
}
|
||||||
|
|
||||||
Compare& compare()
|
Compare& compare()
|
||||||
{
|
{
|
||||||
return empty_base_optimization <Compare>::member();
|
return empty_base_optimization <Compare>::member();
|
||||||
@@ -251,10 +254,12 @@ private:
|
|||||||
using cont_type = typename std::conditional <
|
using cont_type = typename std::conditional <
|
||||||
IsMulti,
|
IsMulti,
|
||||||
typename boost::intrusive::make_multiset <element,
|
typename boost::intrusive::make_multiset <element,
|
||||||
boost::intrusive::constant_time_size <true>
|
boost::intrusive::constant_time_size <true>,
|
||||||
|
boost::intrusive::compare<KeyValueCompare>
|
||||||
>::type,
|
>::type,
|
||||||
typename boost::intrusive::make_set <element,
|
typename boost::intrusive::make_set <element,
|
||||||
boost::intrusive::constant_time_size <true>
|
boost::intrusive::constant_time_size <true>,
|
||||||
|
boost::intrusive::compare<KeyValueCompare>
|
||||||
>::type
|
>::type
|
||||||
>::type;
|
>::type;
|
||||||
|
|
||||||
@@ -1254,6 +1259,7 @@ aged_ordered_container (
|
|||||||
clock_type& clock,
|
clock_type& clock,
|
||||||
Compare const& comp)
|
Compare const& comp)
|
||||||
: m_config (clock, comp)
|
: m_config (clock, comp)
|
||||||
|
, m_cont (comp)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1275,6 +1281,7 @@ aged_ordered_container (
|
|||||||
Compare const& comp,
|
Compare const& comp,
|
||||||
Allocator const& alloc)
|
Allocator const& alloc)
|
||||||
: m_config (clock, comp, alloc)
|
: m_config (clock, comp, alloc)
|
||||||
|
, m_cont (comp)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1297,6 +1304,7 @@ aged_ordered_container (InputIt first, InputIt last,
|
|||||||
clock_type& clock,
|
clock_type& clock,
|
||||||
Compare const& comp)
|
Compare const& comp)
|
||||||
: m_config (clock, comp)
|
: m_config (clock, comp)
|
||||||
|
, m_cont (comp)
|
||||||
{
|
{
|
||||||
insert (first, last);
|
insert (first, last);
|
||||||
}
|
}
|
||||||
@@ -1322,6 +1330,7 @@ aged_ordered_container (InputIt first, InputIt last,
|
|||||||
Compare const& comp,
|
Compare const& comp,
|
||||||
Allocator const& alloc)
|
Allocator const& alloc)
|
||||||
: m_config (clock, comp, alloc)
|
: m_config (clock, comp, alloc)
|
||||||
|
, m_cont (comp)
|
||||||
{
|
{
|
||||||
insert (first, last);
|
insert (first, last);
|
||||||
}
|
}
|
||||||
@@ -1331,6 +1340,7 @@ template <bool IsMulti, bool IsMap, class Key, class T,
|
|||||||
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
||||||
aged_ordered_container (aged_ordered_container const& other)
|
aged_ordered_container (aged_ordered_container const& other)
|
||||||
: m_config (other.m_config)
|
: m_config (other.m_config)
|
||||||
|
, m_cont (other.m_cont.comp())
|
||||||
{
|
{
|
||||||
insert (other.cbegin(), other.cend());
|
insert (other.cbegin(), other.cend());
|
||||||
}
|
}
|
||||||
@@ -1341,6 +1351,7 @@ aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
|||||||
aged_ordered_container (aged_ordered_container const& other,
|
aged_ordered_container (aged_ordered_container const& other,
|
||||||
Allocator const& alloc)
|
Allocator const& alloc)
|
||||||
: m_config (other.m_config, alloc)
|
: m_config (other.m_config, alloc)
|
||||||
|
, m_cont (other.m_cont.comp())
|
||||||
{
|
{
|
||||||
insert (other.cbegin(), other.cend());
|
insert (other.cbegin(), other.cend());
|
||||||
}
|
}
|
||||||
@@ -1361,6 +1372,7 @@ aged_ordered_container <IsMulti, IsMap, Key, T, Clock, Compare, Allocator>::
|
|||||||
aged_ordered_container (aged_ordered_container&& other,
|
aged_ordered_container (aged_ordered_container&& other,
|
||||||
Allocator const& alloc)
|
Allocator const& alloc)
|
||||||
: m_config (std::move (other.m_config), alloc)
|
: m_config (std::move (other.m_config), alloc)
|
||||||
|
, m_cont (std::move(other.m_cont.comp()))
|
||||||
{
|
{
|
||||||
insert (other.cbegin(), other.cend());
|
insert (other.cbegin(), other.cend());
|
||||||
other.clear ();
|
other.clear ();
|
||||||
@@ -1383,6 +1395,7 @@ aged_ordered_container (std::initializer_list <value_type> init,
|
|||||||
clock_type& clock,
|
clock_type& clock,
|
||||||
Compare const& comp)
|
Compare const& comp)
|
||||||
: m_config (clock, comp)
|
: m_config (clock, comp)
|
||||||
|
, m_cont (comp)
|
||||||
{
|
{
|
||||||
insert (init.begin(), init.end());
|
insert (init.begin(), init.end());
|
||||||
}
|
}
|
||||||
@@ -1406,6 +1419,7 @@ aged_ordered_container (std::initializer_list <value_type> init,
|
|||||||
Compare const& comp,
|
Compare const& comp,
|
||||||
Allocator const& alloc)
|
Allocator const& alloc)
|
||||||
: m_config (clock, comp, alloc)
|
: m_config (clock, comp, alloc)
|
||||||
|
, m_cont (comp)
|
||||||
{
|
{
|
||||||
insert (init.begin(), init.end());
|
insert (init.begin(), init.end());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,9 +39,11 @@ public:
|
|||||||
static beast::endian const endian =
|
static beast::endian const endian =
|
||||||
beast::endian::native;
|
beast::endian::native;
|
||||||
|
|
||||||
|
static std::size_t const digest_size =
|
||||||
|
Context::digest_size;
|
||||||
|
|
||||||
using result_type =
|
using result_type =
|
||||||
std::array<std::uint8_t,
|
std::array<std::uint8_t, digest_size>;
|
||||||
Context::digest_size>;
|
|
||||||
|
|
||||||
mac_facade() noexcept
|
mac_facade() noexcept
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -23,8 +23,8 @@
|
|||||||
#include <beast/container/fnv1a.h>
|
#include <beast/container/fnv1a.h>
|
||||||
#include <beast/container/siphash.h>
|
#include <beast/container/siphash.h>
|
||||||
#include <beast/container/xxhasher.h>
|
#include <beast/container/xxhasher.h>
|
||||||
#include <beast/random/rngfill.h>
|
#include <beast/rngfill.h>
|
||||||
#include <beast/random/xor_shift_engine.h>
|
#include <beast/xor_shift_engine.h>
|
||||||
#include <beast/unit_test/suite.h>
|
#include <beast/unit_test/suite.h>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
#include <beast/hash/endian.h>
|
#include <beast/hash/endian.h>
|
||||||
#include <beast/hash/tests/hash_metrics.h>
|
#include <beast/hash/tests/hash_metrics.h>
|
||||||
#include <beast/hash/hash_append.h>
|
#include <beast/hash/hash_append.h>
|
||||||
#include <beast/chrono/chrono_io.h>
|
#include <beast/xor_shift_engine.h>
|
||||||
#include <beast/unit_test/suite.h>
|
#include <beast/unit_test/suite.h>
|
||||||
#include <beast/utility/type_name.h>
|
#include <beast/utility/type_name.h>
|
||||||
#include <array>
|
#include <array>
|
||||||
@@ -284,7 +284,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
SlowKey()
|
SlowKey()
|
||||||
{
|
{
|
||||||
static std::mt19937_64 eng;
|
static beast::xor_shift_engine eng;
|
||||||
std::uniform_int_distribution<short> yeardata(1900, 2014);
|
std::uniform_int_distribution<short> yeardata(1900, 2014);
|
||||||
std::uniform_int_distribution<unsigned> monthdata(1, 12);
|
std::uniform_int_distribution<unsigned> monthdata(1, 12);
|
||||||
std::uniform_int_distribution<unsigned> daydata(1, 28);
|
std::uniform_int_distribution<unsigned> daydata(1, 28);
|
||||||
@@ -331,8 +331,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
FastKey()
|
FastKey()
|
||||||
{
|
{
|
||||||
static std::conditional_t <sizeof(std::size_t)==sizeof(std::uint64_t),
|
static beast::xor_shift_engine eng;
|
||||||
std::mt19937_64, std::mt19937> eng;
|
|
||||||
for (auto& v : m_values)
|
for (auto& v : m_values)
|
||||||
v = eng();
|
v = eng();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -166,15 +166,15 @@ windowed_score (FwdIter first, FwdIter last)
|
|||||||
int maxwidth = 20;
|
int maxwidth = 20;
|
||||||
// We need at least 5 keys per bin to reliably test distribution biases
|
// We need at least 5 keys per bin to reliably test distribution biases
|
||||||
// down to 1%, so don't bother to test sparser distributions than that
|
// down to 1%, so don't bother to test sparser distributions than that
|
||||||
while (static_cast<double>(size) / (1 << maxwidth) < 5.0)
|
while (static_cast<double>(size) / (1ull << maxwidth) < 5.0)
|
||||||
maxwidth--;
|
maxwidth--;
|
||||||
double worst = 0;
|
double worst = 0;
|
||||||
std::vector <int> bins (1 << maxwidth);
|
std::vector <int> bins (1ull << maxwidth);
|
||||||
int const hashbits = sizeof(std::size_t) * CHAR_BIT;
|
int const hashbits = sizeof(std::size_t) * CHAR_BIT;
|
||||||
for (int start = 0; start < hashbits; ++start)
|
for (int start = 0; start < hashbits; ++start)
|
||||||
{
|
{
|
||||||
int width = maxwidth;
|
int width = maxwidth;
|
||||||
bins.assign (1 << width, 0);
|
bins.assign (1ull << width, 0);
|
||||||
for (auto iter (first); iter != last; ++iter)
|
for (auto iter (first); iter != last; ++iter)
|
||||||
++bins[detail::window(&*iter, start, width)];
|
++bins[detail::window(&*iter, start, width)];
|
||||||
// Test the distribution, then fold the bins in half,
|
// Test the distribution, then fold the bins in half,
|
||||||
|
|||||||
@@ -23,9 +23,8 @@
|
|||||||
#include <beast/hash/fnv1a.h>
|
#include <beast/hash/fnv1a.h>
|
||||||
#include <beast/hash/siphash.h>
|
#include <beast/hash/siphash.h>
|
||||||
#include <beast/hash/xxhasher.h>
|
#include <beast/hash/xxhasher.h>
|
||||||
#include <beast/chrono/chrono_io.h>
|
#include <beast/rngfill.h>
|
||||||
#include <beast/random/rngfill.h>
|
#include <beast/xor_shift_engine.h>
|
||||||
#include <beast/random/xor_shift_engine.h>
|
|
||||||
#include <beast/unit_test/suite.h>
|
#include <beast/unit_test/suite.h>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
@@ -61,7 +60,7 @@ public:
|
|||||||
}
|
}
|
||||||
auto const elapsed = clock_type::now() - start;
|
auto const elapsed = clock_type::now() - start;
|
||||||
log << setw(12) << what << " " <<
|
log << setw(12) << what << " " <<
|
||||||
duration<double>(elapsed) << "s";
|
duration<double>(elapsed).count() << "s";
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
#include <beast/http/impl/basic_parser.cpp>
|
#include <beast/http/impl/basic_parser.cpp>
|
||||||
#include <beast/http/impl/joyent_parser.cpp>
|
#include <beast/http/impl/joyent_parser.cpp>
|
||||||
#include <beast/http/impl/method.cpp>
|
#include <beast/http/impl/method.cpp>
|
||||||
#include <beast/http/impl/raw_parser.cpp>
|
|
||||||
#include <beast/http/impl/URL.cpp>
|
#include <beast/http/impl/URL.cpp>
|
||||||
|
|
||||||
#include <beast/http/tests/chunked_encoder.test.cpp>
|
#include <beast/http/tests/chunked_encoder.test.cpp>
|
||||||
|
|||||||
@@ -74,6 +74,8 @@ private:
|
|||||||
cb_t on_headers_complete;
|
cb_t on_headers_complete;
|
||||||
data_cb_t on_body;
|
data_cb_t on_body;
|
||||||
cb_t on_message_complete;
|
cb_t on_message_complete;
|
||||||
|
cb_t on_chunk_header;
|
||||||
|
cb_t on_chunk_complete;
|
||||||
};
|
};
|
||||||
|
|
||||||
char state_ [sizeof(state_t)];
|
char state_ [sizeof(state_t)];
|
||||||
@@ -221,6 +223,8 @@ private:
|
|||||||
int do_headers_complete ();
|
int do_headers_complete ();
|
||||||
int do_body (char const* in, std::size_t bytes);
|
int do_body (char const* in, std::size_t bytes);
|
||||||
int do_message_complete ();
|
int do_message_complete ();
|
||||||
|
int do_chunk_header();
|
||||||
|
int do_chunk_complete();
|
||||||
|
|
||||||
static int cb_message_start (joyent::http_parser*);
|
static int cb_message_start (joyent::http_parser*);
|
||||||
static int cb_url (joyent::http_parser*, char const*, std::size_t);
|
static int cb_url (joyent::http_parser*, char const*, std::size_t);
|
||||||
@@ -230,6 +234,8 @@ private:
|
|||||||
static int cb_headers_complete (joyent::http_parser*);
|
static int cb_headers_complete (joyent::http_parser*);
|
||||||
static int cb_body (joyent::http_parser*, char const*, std::size_t);
|
static int cb_body (joyent::http_parser*, char const*, std::size_t);
|
||||||
static int cb_message_complete (joyent::http_parser*);
|
static int cb_message_complete (joyent::http_parser*);
|
||||||
|
static int cb_chunk_header (joyent::http_parser*);
|
||||||
|
static int cb_chunk_complete (joyent::http_parser*);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class ConstBufferSequence>
|
template <class ConstBufferSequence>
|
||||||
|
|||||||
@@ -64,6 +64,9 @@ private:
|
|||||||
template <class String>
|
template <class String>
|
||||||
bool
|
bool
|
||||||
operator() (element const& lhs, String const& rhs) const;
|
operator() (element const& lhs, String const& rhs) const;
|
||||||
|
|
||||||
|
bool
|
||||||
|
operator() (element const& lhs, element const& rhs) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct transform
|
struct transform
|
||||||
@@ -81,7 +84,8 @@ private:
|
|||||||
>::type;
|
>::type;
|
||||||
|
|
||||||
using set_t = boost::intrusive::make_set <element,
|
using set_t = boost::intrusive::make_set <element,
|
||||||
boost::intrusive::constant_time_size <true>
|
boost::intrusive::constant_time_size <true>,
|
||||||
|
boost::intrusive::compare<less>
|
||||||
>::type;
|
>::type;
|
||||||
|
|
||||||
list_t list_;
|
list_t list_;
|
||||||
@@ -187,6 +191,14 @@ headers::less::operator() (
|
|||||||
return beast::ci_less::operator() (lhs.data.first, rhs);
|
return beast::ci_less::operator() (lhs.data.first, rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
bool
|
||||||
|
headers::less::operator() (
|
||||||
|
element const& lhs, element const& rhs) const
|
||||||
|
{
|
||||||
|
return beast::ci_less::operator() (lhs.data.first, rhs.data.first);
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
inline
|
inline
|
||||||
|
|||||||
@@ -93,6 +93,8 @@ basic_parser::basic_parser (bool request) noexcept
|
|||||||
h->on_headers_complete = &basic_parser::cb_headers_complete;
|
h->on_headers_complete = &basic_parser::cb_headers_complete;
|
||||||
h->on_body = &basic_parser::cb_body;
|
h->on_body = &basic_parser::cb_body;
|
||||||
h->on_message_complete = &basic_parser::cb_message_complete;
|
h->on_message_complete = &basic_parser::cb_message_complete;
|
||||||
|
h->on_chunk_header = &basic_parser::cb_chunk_header;
|
||||||
|
h->on_chunk_complete = &basic_parser::cb_chunk_complete;
|
||||||
|
|
||||||
joyent::http_parser_init (s, request
|
joyent::http_parser_init (s, request
|
||||||
? joyent::http_parser_type::HTTP_REQUEST
|
? joyent::http_parser_type::HTTP_REQUEST
|
||||||
@@ -231,6 +233,18 @@ basic_parser::do_message_complete ()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
basic_parser::do_chunk_header()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
basic_parser::do_chunk_complete()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -295,5 +309,19 @@ basic_parser::cb_message_complete (joyent::http_parser* p)
|
|||||||
p->data)->do_message_complete();
|
p->data)->do_message_complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
basic_parser::cb_chunk_header (joyent::http_parser* p)
|
||||||
|
{
|
||||||
|
return reinterpret_cast <basic_parser*> (
|
||||||
|
p->data)->do_chunk_header();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
basic_parser::cb_chunk_complete (joyent::http_parser* p)
|
||||||
|
{
|
||||||
|
return reinterpret_cast <basic_parser*> (
|
||||||
|
p->data)->do_chunk_complete();
|
||||||
|
}
|
||||||
|
|
||||||
} // http
|
} // http
|
||||||
} // beast
|
} // beast
|
||||||
|
|||||||
@@ -5,12 +5,15 @@ tags
|
|||||||
test
|
test
|
||||||
test_g
|
test_g
|
||||||
test_fast
|
test_fast
|
||||||
|
bench
|
||||||
url_parser
|
url_parser
|
||||||
parsertrace
|
parsertrace
|
||||||
parsertrace_g
|
parsertrace_g
|
||||||
*.mk
|
*.mk
|
||||||
*.Makefile
|
*.Makefile
|
||||||
*.so.*
|
*.so.*
|
||||||
|
*.exe.*
|
||||||
|
*.exe
|
||||||
*.a
|
*.a
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,3 +5,4 @@ Salman Haq <salman.haq@asti-usa.com>
|
|||||||
Simon Zimmermann <simonz05@gmail.com>
|
Simon Zimmermann <simonz05@gmail.com>
|
||||||
Thomas LE ROUX <thomas@november-eleven.fr> LE ROUX Thomas <thomas@procheo.fr>
|
Thomas LE ROUX <thomas@november-eleven.fr> LE ROUX Thomas <thomas@procheo.fr>
|
||||||
Thomas LE ROUX <thomas@november-eleven.fr> Thomas LE ROUX <thomas@procheo.fr>
|
Thomas LE ROUX <thomas@november-eleven.fr> Thomas LE ROUX <thomas@procheo.fr>
|
||||||
|
Fedor Indutny <fedor@indutny.com>
|
||||||
|
|||||||
@@ -10,4 +10,4 @@ script:
|
|||||||
notifications:
|
notifications:
|
||||||
email: false
|
email: false
|
||||||
irc:
|
irc:
|
||||||
- "irc.freenode.net#libuv"
|
- "irc.freenode.net#node-ci"
|
||||||
|
|||||||
@@ -39,11 +39,30 @@ BogDan Vatra <bogdan@kde.org>
|
|||||||
Peter Faiman <peter@thepicard.org>
|
Peter Faiman <peter@thepicard.org>
|
||||||
Corey Richardson <corey@octayn.net>
|
Corey Richardson <corey@octayn.net>
|
||||||
Tóth Tamás <tomika_nospam@freemail.hu>
|
Tóth Tamás <tomika_nospam@freemail.hu>
|
||||||
Patrik Stutz <patrik.stutz@gmail.com>
|
|
||||||
Cam Swords <cam.swords@gmail.com>
|
Cam Swords <cam.swords@gmail.com>
|
||||||
Chris Dickinson <christopher.s.dickinson@gmail.com>
|
Chris Dickinson <christopher.s.dickinson@gmail.com>
|
||||||
Uli Köhler <ukoehler@btronik.de>
|
Uli Köhler <ukoehler@btronik.de>
|
||||||
Charlie Somerville <charlie@charliesomerville.com>
|
Charlie Somerville <charlie@charliesomerville.com>
|
||||||
|
Patrik Stutz <patrik.stutz@gmail.com>
|
||||||
Fedor Indutny <fedor.indutny@gmail.com>
|
Fedor Indutny <fedor.indutny@gmail.com>
|
||||||
runner <runner.mei@gmail.com>
|
runner <runner.mei@gmail.com>
|
||||||
Alexis Campailla <alexis@janeasystems.com>
|
Alexis Campailla <alexis@janeasystems.com>
|
||||||
|
David Wragg <david@wragg.org>
|
||||||
|
Vinnie Falco <vinnie.falco@gmail.com>
|
||||||
|
Alex Butum <alexbutum@linux.com>
|
||||||
|
Rex Feng <rexfeng@gmail.com>
|
||||||
|
Alex Kocharin <alex@kocharin.ru>
|
||||||
|
Mark Koopman <markmontymark@yahoo.com>
|
||||||
|
Helge Heß <me@helgehess.eu>
|
||||||
|
Alexis La Goutte <alexis.lagoutte@gmail.com>
|
||||||
|
George Miroshnykov <george.miroshnykov@gmail.com>
|
||||||
|
Maciej Małecki <me@mmalecki.com>
|
||||||
|
Marc O'Morain <github.com@marcomorain.com>
|
||||||
|
Jeff Pinner <jpinner@twitter.com>
|
||||||
|
Timothy J Fontaine <tjfontaine@gmail.com>
|
||||||
|
Akagi201 <akagi201@gmail.com>
|
||||||
|
Romain Giraud <giraud.romain@gmail.com>
|
||||||
|
Jay Satiro <raysatiro@yahoo.com>
|
||||||
|
Arne Steen <Arne.Steen@gmx.de>
|
||||||
|
Kjell Schubert <kjell.schubert@gmail.com>
|
||||||
|
Olivier Mengué <dolmen@cpan.org>
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
Contributors must agree to the Contributor License Agreement before patches
|
|
||||||
can be accepted.
|
|
||||||
|
|
||||||
http://spreadsheets2.google.com/viewform?hl=en&formkey=dDJXOGUwbzlYaWM4cHN1MERwQS1CSnc6MQ
|
|
||||||
@@ -19,32 +19,54 @@
|
|||||||
# IN THE SOFTWARE.
|
# IN THE SOFTWARE.
|
||||||
|
|
||||||
PLATFORM ?= $(shell sh -c 'uname -s | tr "[A-Z]" "[a-z]"')
|
PLATFORM ?= $(shell sh -c 'uname -s | tr "[A-Z]" "[a-z]"')
|
||||||
SONAME ?= libhttp_parser.so.2.2.1
|
HELPER ?=
|
||||||
|
BINEXT ?=
|
||||||
|
ifeq (darwin,$(PLATFORM))
|
||||||
|
SONAME ?= libhttp_parser.2.6.1.dylib
|
||||||
|
SOEXT ?= dylib
|
||||||
|
else ifeq (wine,$(PLATFORM))
|
||||||
|
CC = winegcc
|
||||||
|
BINEXT = .exe.so
|
||||||
|
HELPER = wine
|
||||||
|
else
|
||||||
|
SONAME ?= libhttp_parser.so.2.6.1
|
||||||
|
SOEXT ?= so
|
||||||
|
endif
|
||||||
|
|
||||||
CC?=gcc
|
CC?=gcc
|
||||||
AR?=ar
|
AR?=ar
|
||||||
|
|
||||||
|
CPPFLAGS ?=
|
||||||
|
LDFLAGS ?=
|
||||||
|
|
||||||
CPPFLAGS += -I.
|
CPPFLAGS += -I.
|
||||||
CPPFLAGS_DEBUG = $(CPPFLAGS) -DHTTP_PARSER_STRICT=1
|
CPPFLAGS_DEBUG = $(CPPFLAGS) -DHTTP_PARSER_STRICT=1
|
||||||
CPPFLAGS_DEBUG += $(CPPFLAGS_DEBUG_EXTRA)
|
CPPFLAGS_DEBUG += $(CPPFLAGS_DEBUG_EXTRA)
|
||||||
CPPFLAGS_FAST = $(CPPFLAGS) -DHTTP_PARSER_STRICT=0
|
CPPFLAGS_FAST = $(CPPFLAGS) -DHTTP_PARSER_STRICT=0
|
||||||
CPPFLAGS_FAST += $(CPPFLAGS_FAST_EXTRA)
|
CPPFLAGS_FAST += $(CPPFLAGS_FAST_EXTRA)
|
||||||
|
CPPFLAGS_BENCH = $(CPPFLAGS_FAST)
|
||||||
|
|
||||||
CFLAGS += -Wall -Wextra -Werror
|
CFLAGS += -Wall -Wextra -Werror
|
||||||
CFLAGS_DEBUG = $(CFLAGS) -O0 -g $(CFLAGS_DEBUG_EXTRA)
|
CFLAGS_DEBUG = $(CFLAGS) -O0 -g $(CFLAGS_DEBUG_EXTRA)
|
||||||
CFLAGS_FAST = $(CFLAGS) -O3 $(CFLAGS_FAST_EXTRA)
|
CFLAGS_FAST = $(CFLAGS) -O3 $(CFLAGS_FAST_EXTRA)
|
||||||
|
CFLAGS_BENCH = $(CFLAGS_FAST) -Wno-unused-parameter
|
||||||
CFLAGS_LIB = $(CFLAGS_FAST) -fPIC
|
CFLAGS_LIB = $(CFLAGS_FAST) -fPIC
|
||||||
|
|
||||||
LDFLAGS_LIB = $(LDFLAGS) -shared
|
LDFLAGS_LIB = $(LDFLAGS) -shared
|
||||||
|
|
||||||
|
INSTALL ?= install
|
||||||
|
PREFIX ?= $(DESTDIR)/usr/local
|
||||||
|
LIBDIR = $(PREFIX)/lib
|
||||||
|
INCLUDEDIR = $(PREFIX)/include
|
||||||
|
|
||||||
ifneq (darwin,$(PLATFORM))
|
ifneq (darwin,$(PLATFORM))
|
||||||
# TODO(bnoordhuis) The native SunOS linker expects -h rather than -soname...
|
# TODO(bnoordhuis) The native SunOS linker expects -h rather than -soname...
|
||||||
LDFLAGS_LIB += -Wl,-soname=$(SONAME)
|
LDFLAGS_LIB += -Wl,-soname=$(SONAME)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
test: test_g test_fast
|
test: test_g test_fast
|
||||||
./test_g
|
$(HELPER) ./test_g$(BINEXT)
|
||||||
./test_fast
|
$(HELPER) ./test_fast$(BINEXT)
|
||||||
|
|
||||||
test_g: http_parser_g.o test_g.o
|
test_g: http_parser_g.o test_g.o
|
||||||
$(CC) $(CFLAGS_DEBUG) $(LDFLAGS) http_parser_g.o test_g.o -o $@
|
$(CC) $(CFLAGS_DEBUG) $(LDFLAGS) http_parser_g.o test_g.o -o $@
|
||||||
@@ -61,11 +83,17 @@ test_fast: http_parser.o test.o http_parser.h
|
|||||||
test.o: test.c http_parser.h Makefile
|
test.o: test.c http_parser.h Makefile
|
||||||
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) -c test.c -o $@
|
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) -c test.c -o $@
|
||||||
|
|
||||||
|
bench: http_parser.o bench.o
|
||||||
|
$(CC) $(CFLAGS_BENCH) $(LDFLAGS) http_parser.o bench.o -o $@
|
||||||
|
|
||||||
|
bench.o: bench.c http_parser.h Makefile
|
||||||
|
$(CC) $(CPPFLAGS_BENCH) $(CFLAGS_BENCH) -c bench.c -o $@
|
||||||
|
|
||||||
http_parser.o: http_parser.c http_parser.h Makefile
|
http_parser.o: http_parser.c http_parser.h Makefile
|
||||||
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) -c http_parser.c
|
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) -c http_parser.c
|
||||||
|
|
||||||
test-run-timed: test_fast
|
test-run-timed: test_fast
|
||||||
while(true) do time ./test_fast > /dev/null; done
|
while(true) do time $(HELPER) ./test_fast$(BINEXT) > /dev/null; done
|
||||||
|
|
||||||
test-valgrind: test_g
|
test-valgrind: test_g
|
||||||
valgrind ./test_g
|
valgrind ./test_g
|
||||||
@@ -86,20 +114,36 @@ url_parser_g: http_parser_g.o contrib/url_parser.c
|
|||||||
$(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) $^ -o $@
|
$(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) $^ -o $@
|
||||||
|
|
||||||
parsertrace: http_parser.o contrib/parsertrace.c
|
parsertrace: http_parser.o contrib/parsertrace.c
|
||||||
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) $^ -o parsertrace
|
$(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) $^ -o parsertrace$(BINEXT)
|
||||||
|
|
||||||
parsertrace_g: http_parser_g.o contrib/parsertrace.c
|
parsertrace_g: http_parser_g.o contrib/parsertrace.c
|
||||||
$(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) $^ -o parsertrace_g
|
$(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) $^ -o parsertrace_g$(BINEXT)
|
||||||
|
|
||||||
tags: http_parser.c http_parser.h test.c
|
tags: http_parser.c http_parser.h test.c
|
||||||
ctags $^
|
ctags $^
|
||||||
|
|
||||||
|
install: library
|
||||||
|
$(INSTALL) -D http_parser.h $(INCLUDEDIR)/http_parser.h
|
||||||
|
$(INSTALL) -D $(SONAME) $(LIBDIR)/$(SONAME)
|
||||||
|
ln -s $(LIBDIR)/$(SONAME) $(LIBDIR)/libhttp_parser.$(SOEXT)
|
||||||
|
|
||||||
|
install-strip: library
|
||||||
|
$(INSTALL) -D http_parser.h $(INCLUDEDIR)/http_parser.h
|
||||||
|
$(INSTALL) -D -s $(SONAME) $(LIBDIR)/$(SONAME)
|
||||||
|
ln -s $(LIBDIR)/$(SONAME) $(LIBDIR)/libhttp_parser.$(SOEXT)
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
rm $(INCLUDEDIR)/http_parser.h
|
||||||
|
rm $(LIBDIR)/$(SONAME)
|
||||||
|
rm $(LIBDIR)/libhttp_parser.so
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o *.a tags test test_fast test_g \
|
rm -f *.o *.a tags test test_fast test_g \
|
||||||
http_parser.tar libhttp_parser.so.* \
|
http_parser.tar libhttp_parser.so.* \
|
||||||
url_parser url_parser_g parsertrace parsertrace_g
|
url_parser url_parser_g parsertrace parsertrace_g \
|
||||||
|
*.exe *.exe.so
|
||||||
|
|
||||||
contrib/url_parser.c: http_parser.h
|
contrib/url_parser.c: http_parser.h
|
||||||
contrib/parsertrace.c: http_parser.h
|
contrib/parsertrace.c: http_parser.h
|
||||||
|
|
||||||
.PHONY: clean package test-run test-run-timed test-valgrind
|
.PHONY: clean package test-run test-run-timed test-valgrind install install-strip uninstall
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
HTTP Parser
|
HTTP Parser
|
||||||
===========
|
===========
|
||||||
|
|
||||||
[](https://travis-ci.org/joyent/http-parser)
|
[](https://travis-ci.org/nodejs/http-parser)
|
||||||
|
|
||||||
This is a parser for HTTP messages written in C. It parses both requests and
|
This is a parser for HTTP messages written in C. It parses both requests and
|
||||||
responses. The parser is designed to be used in performance HTTP
|
responses. The parser is designed to be used in performance HTTP
|
||||||
@@ -61,7 +61,7 @@ if (recved < 0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Start up / continue the parser.
|
/* Start up / continue the parser.
|
||||||
* Note we pass recved==0 to signal that EOF has been recieved.
|
* Note we pass recved==0 to signal that EOF has been received.
|
||||||
*/
|
*/
|
||||||
nparsed = http_parser_execute(parser, &settings, buf, recved);
|
nparsed = http_parser_execute(parser, &settings, buf, recved);
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ if (parser->upgrade) {
|
|||||||
HTTP needs to know where the end of the stream is. For example, sometimes
|
HTTP needs to know where the end of the stream is. For example, sometimes
|
||||||
servers send responses without Content-Length and expect the client to
|
servers send responses without Content-Length and expect the client to
|
||||||
consume input (for the body) until EOF. To tell http_parser about EOF, give
|
consume input (for the body) until EOF. To tell http_parser about EOF, give
|
||||||
`0` as the forth parameter to `http_parser_execute()`. Callbacks and errors
|
`0` as the fourth parameter to `http_parser_execute()`. Callbacks and errors
|
||||||
can still be encountered during an EOF, so one must still be prepared
|
can still be encountered during an EOF, so one must still be prepared
|
||||||
to receive them.
|
to receive them.
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ The Special Problem of Upgrade
|
|||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
HTTP supports upgrading the connection to a different protocol. An
|
HTTP supports upgrading the connection to a different protocol. An
|
||||||
increasingly common example of this is the Web Socket protocol which sends
|
increasingly common example of this is the WebSocket protocol which sends
|
||||||
a request like
|
a request like
|
||||||
|
|
||||||
GET /demo HTTP/1.1
|
GET /demo HTTP/1.1
|
||||||
@@ -106,11 +106,11 @@ a request like
|
|||||||
|
|
||||||
followed by non-HTTP data.
|
followed by non-HTTP data.
|
||||||
|
|
||||||
(See http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75 for more
|
(See [RFC6455](https://tools.ietf.org/html/rfc6455) for more information the
|
||||||
information the Web Socket protocol.)
|
WebSocket protocol.)
|
||||||
|
|
||||||
To support this, the parser will treat this as a normal HTTP message without a
|
To support this, the parser will treat this as a normal HTTP message without a
|
||||||
body. Issuing both on_headers_complete and on_message_complete callbacks. However
|
body, issuing both on_headers_complete and on_message_complete callbacks. However
|
||||||
http_parser_execute() will stop parsing at the end of the headers and return.
|
http_parser_execute() will stop parsing at the end of the headers and return.
|
||||||
|
|
||||||
The user is expected to check if `parser->upgrade` has been set to 1 after
|
The user is expected to check if `parser->upgrade` has been set to 1 after
|
||||||
@@ -128,15 +128,78 @@ save certain data for later usage, you can do that from the callbacks.
|
|||||||
|
|
||||||
There are two types of callbacks:
|
There are two types of callbacks:
|
||||||
|
|
||||||
* notification `using http_cb = int (*) (http_parser*);`
|
* notification `typedef int (*http_cb) (http_parser*);`
|
||||||
Callbacks: on_message_begin, on_headers_complete, on_message_complete.
|
Callbacks: on_message_begin, on_headers_complete, on_message_complete.
|
||||||
* data `using http_data_cb = int (*) (http_parser*, const char *at, size_t length);`
|
* data `typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);`
|
||||||
Callbacks: (requests only) on_uri,
|
Callbacks: (requests only) on_url,
|
||||||
(common) on_header_field, on_header_value, on_body;
|
(common) on_header_field, on_header_value, on_body;
|
||||||
|
|
||||||
Callbacks must return 0 on success. Returning a non-zero value indicates
|
Callbacks must return 0 on success. Returning a non-zero value indicates
|
||||||
error to the parser, making it exit immediately.
|
error to the parser, making it exit immediately.
|
||||||
|
|
||||||
|
For cases where it is necessary to pass local information to/from a callback,
|
||||||
|
the `http_parser` object's `data` field can be used.
|
||||||
|
An example of such a case is when using threads to handle a socket connection,
|
||||||
|
parse a request, and then give a response over that socket. By instantiation
|
||||||
|
of a thread-local struct containing relevant data (e.g. accepted socket,
|
||||||
|
allocated memory for callbacks to write into, etc), a parser's callbacks are
|
||||||
|
able to communicate data between the scope of the thread and the scope of the
|
||||||
|
callback in a threadsafe manner. This allows http-parser to be used in
|
||||||
|
multi-threaded contexts.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```
|
||||||
|
typedef struct {
|
||||||
|
socket_t sock;
|
||||||
|
void* buffer;
|
||||||
|
int buf_len;
|
||||||
|
} custom_data_t;
|
||||||
|
|
||||||
|
|
||||||
|
int my_url_callback(http_parser* parser, const char *at, size_t length) {
|
||||||
|
/* access to thread local custom_data_t struct.
|
||||||
|
Use this access save parsed data for later use into thread local
|
||||||
|
buffer, or communicate over socket
|
||||||
|
*/
|
||||||
|
parser->data;
|
||||||
|
...
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
void http_parser_thread(socket_t sock) {
|
||||||
|
int nparsed = 0;
|
||||||
|
/* allocate memory for user data */
|
||||||
|
custom_data_t *my_data = malloc(sizeof(custom_data_t));
|
||||||
|
|
||||||
|
/* some information for use by callbacks.
|
||||||
|
* achieves thread -> callback information flow */
|
||||||
|
my_data->sock = sock;
|
||||||
|
|
||||||
|
/* instantiate a thread-local parser */
|
||||||
|
http_parser *parser = malloc(sizeof(http_parser));
|
||||||
|
http_parser_init(parser, HTTP_REQUEST); /* initialise parser */
|
||||||
|
/* this custom data reference is accessible through the reference to the
|
||||||
|
parser supplied to callback functions */
|
||||||
|
parser->data = my_data;
|
||||||
|
|
||||||
|
http_parser_settings settings; / * set up callbacks */
|
||||||
|
settings.on_url = my_url_callback;
|
||||||
|
|
||||||
|
/* execute parser */
|
||||||
|
nparsed = http_parser_execute(parser, &settings, buf, recved);
|
||||||
|
|
||||||
|
...
|
||||||
|
/* parsed information copied from callback.
|
||||||
|
can now perform action on data copied into thread-local memory from callbacks.
|
||||||
|
achieves callback -> thread information flow */
|
||||||
|
my_data->buffer;
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
In case you parse HTTP message in chunks (i.e. `read()` request line
|
In case you parse HTTP message in chunks (i.e. `read()` request line
|
||||||
from socket, parse, read half headers, parse, etc) your data callbacks
|
from socket, parse, read half headers, parse, etc) your data callbacks
|
||||||
may be called more than once. Http-parser guarantees that data pointer is only
|
may be called more than once. Http-parser guarantees that data pointer is only
|
||||||
@@ -145,7 +208,7 @@ buffer to avoid copying memory around if this fits your application.
|
|||||||
|
|
||||||
Reading headers may be a tricky task if you read/parse headers partially.
|
Reading headers may be a tricky task if you read/parse headers partially.
|
||||||
Basically, you need to remember whether last header callback was field or value
|
Basically, you need to remember whether last header callback was field or value
|
||||||
and apply following logic:
|
and apply the following logic:
|
||||||
|
|
||||||
(on_header_field and on_header_value shortened to on_h_*)
|
(on_header_field and on_header_value shortened to on_h_*)
|
||||||
------------------------ ------------ --------------------------------------------
|
------------------------ ------------ --------------------------------------------
|
||||||
|
|||||||
111
src/beast/beast/http/impl/http-parser/bench.c
Normal file
111
src/beast/beast/http/impl/http-parser/bench.c
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
/* Copyright Fedor Indutny. 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, 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.
|
||||||
|
*/
|
||||||
|
#include "http_parser.h"
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
static const char data[] =
|
||||||
|
"POST /joyent/http-parser HTTP/1.1\r\n"
|
||||||
|
"Host: github.com\r\n"
|
||||||
|
"DNT: 1\r\n"
|
||||||
|
"Accept-Encoding: gzip, deflate, sdch\r\n"
|
||||||
|
"Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4\r\n"
|
||||||
|
"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) "
|
||||||
|
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||||
|
"Chrome/39.0.2171.65 Safari/537.36\r\n"
|
||||||
|
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,"
|
||||||
|
"image/webp,*/*;q=0.8\r\n"
|
||||||
|
"Referer: https://github.com/joyent/http-parser\r\n"
|
||||||
|
"Connection: keep-alive\r\n"
|
||||||
|
"Transfer-Encoding: chunked\r\n"
|
||||||
|
"Cache-Control: max-age=0\r\n\r\nb\r\nhello world\r\n0\r\n\r\n";
|
||||||
|
static const size_t data_len = sizeof(data) - 1;
|
||||||
|
|
||||||
|
static int on_info(http_parser* p) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int on_data(http_parser* p, const char *at, size_t length) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static http_parser_settings settings = {
|
||||||
|
.on_message_begin = on_info,
|
||||||
|
.on_headers_complete = on_info,
|
||||||
|
.on_message_complete = on_info,
|
||||||
|
.on_header_field = on_data,
|
||||||
|
.on_header_value = on_data,
|
||||||
|
.on_url = on_data,
|
||||||
|
.on_status = on_data,
|
||||||
|
.on_body = on_data
|
||||||
|
};
|
||||||
|
|
||||||
|
int bench(int iter_count, int silent) {
|
||||||
|
struct http_parser parser;
|
||||||
|
int i;
|
||||||
|
int err;
|
||||||
|
struct timeval start;
|
||||||
|
struct timeval end;
|
||||||
|
float rps;
|
||||||
|
|
||||||
|
if (!silent) {
|
||||||
|
err = gettimeofday(&start, NULL);
|
||||||
|
assert(err == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < iter_count; i++) {
|
||||||
|
size_t parsed;
|
||||||
|
http_parser_init(&parser, HTTP_REQUEST);
|
||||||
|
|
||||||
|
parsed = http_parser_execute(&parser, &settings, data, data_len);
|
||||||
|
assert(parsed == data_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!silent) {
|
||||||
|
err = gettimeofday(&end, NULL);
|
||||||
|
assert(err == 0);
|
||||||
|
|
||||||
|
fprintf(stdout, "Benchmark result:\n");
|
||||||
|
|
||||||
|
rps = (float) (end.tv_sec - start.tv_sec) +
|
||||||
|
(end.tv_usec - start.tv_usec) * 1e-6f;
|
||||||
|
fprintf(stdout, "Took %f seconds to run\n", rps);
|
||||||
|
|
||||||
|
rps = (float) iter_count / rps;
|
||||||
|
fprintf(stdout, "%f req/sec\n", rps);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
if (argc == 2 && strcmp(argv[1], "infinite") == 0) {
|
||||||
|
for (;;)
|
||||||
|
bench(5000000, 1);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return bench(5000000, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -111,14 +111,14 @@ int main(int argc, char* argv[]) {
|
|||||||
FILE* file = fopen(filename, "r");
|
FILE* file = fopen(filename, "r");
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
perror("fopen");
|
perror("fopen");
|
||||||
return EXIT_FAILURE;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
fseek(file, 0, SEEK_END);
|
fseek(file, 0, SEEK_END);
|
||||||
long file_length = ftell(file);
|
long file_length = ftell(file);
|
||||||
if (file_length == -1) {
|
if (file_length == -1) {
|
||||||
perror("ftell");
|
perror("ftell");
|
||||||
return EXIT_FAILURE;
|
goto fail;
|
||||||
}
|
}
|
||||||
fseek(file, 0, SEEK_SET);
|
fseek(file, 0, SEEK_SET);
|
||||||
|
|
||||||
@@ -126,7 +126,7 @@ int main(int argc, char* argv[]) {
|
|||||||
if (fread(data, 1, file_length, file) != (size_t)file_length) {
|
if (fread(data, 1, file_length, file) != (size_t)file_length) {
|
||||||
fprintf(stderr, "couldn't read entire file\n");
|
fprintf(stderr, "couldn't read entire file\n");
|
||||||
free(data);
|
free(data);
|
||||||
return EXIT_FAILURE;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
http_parser_settings settings;
|
http_parser_settings settings;
|
||||||
@@ -149,8 +149,12 @@ int main(int argc, char* argv[]) {
|
|||||||
"Error: %s (%s)\n",
|
"Error: %s (%s)\n",
|
||||||
http_errno_description(HTTP_PARSER_ERRNO(&parser)),
|
http_errno_description(HTTP_PARSER_ERRNO(&parser)),
|
||||||
http_errno_name(HTTP_PARSER_ERRNO(&parser)));
|
http_errno_name(HTTP_PARSER_ERRNO(&parser)));
|
||||||
return EXIT_FAILURE;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
fclose(file);
|
||||||
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ dump_url (const char *url, const struct http_parser_url *u)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\tfield_data[%u]: off: %u len: %u part: \"%.*s\n",
|
printf("\tfield_data[%u]: off: %u, len: %u, part: %.*s\n",
|
||||||
i,
|
i,
|
||||||
u->field_data[i].off,
|
u->field_data[i].off,
|
||||||
u->field_data[i].len,
|
u->field_data[i].len,
|
||||||
@@ -24,16 +24,19 @@ dump_url (const char *url, const struct http_parser_url *u)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char ** argv) {
|
int main(int argc, char ** argv) {
|
||||||
|
struct http_parser_url u;
|
||||||
|
int len, connect, result;
|
||||||
|
|
||||||
if (argc != 3) {
|
if (argc != 3) {
|
||||||
printf("Syntax : %s connect|get url\n", argv[0]);
|
printf("Syntax : %s connect|get url\n", argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
struct http_parser_url u;
|
len = strlen(argv[2]);
|
||||||
int len = strlen(argv[2]);
|
connect = strcmp("connect", argv[1]) == 0 ? 1 : 0;
|
||||||
int connect = strcmp("connect", argv[1]) == 0 ? 1 : 0;
|
|
||||||
printf("Parsing %s, connect %d\n", argv[2], connect);
|
printf("Parsing %s, connect %d\n", argv[2], connect);
|
||||||
|
|
||||||
int result = http_parser_parse_url(argv[2], len, connect, &u);
|
http_parser_url_init(&u);
|
||||||
|
result = http_parser_parse_url(argv[2], len, connect, &u);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
printf("Parse error : %d\n", result);
|
printf("Parse error : %d\n", result);
|
||||||
return result;
|
return result;
|
||||||
@@ -41,4 +44,4 @@ int main(int argc, char ** argv) {
|
|||||||
printf("Parse ok, result : \n");
|
printf("Parse ok, result : \n");
|
||||||
dump_url(argv[2], &u);
|
dump_url(argv[2], &u);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -27,11 +27,12 @@ extern "C" {
|
|||||||
|
|
||||||
/* Also update SONAME in the Makefile whenever you change these. */
|
/* Also update SONAME in the Makefile whenever you change these. */
|
||||||
#define HTTP_PARSER_VERSION_MAJOR 2
|
#define HTTP_PARSER_VERSION_MAJOR 2
|
||||||
#define HTTP_PARSER_VERSION_MINOR 2
|
#define HTTP_PARSER_VERSION_MINOR 6
|
||||||
#define HTTP_PARSER_VERSION_PATCH 1
|
#define HTTP_PARSER_VERSION_PATCH 1
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#if defined(_WIN32) && !defined(__MINGW32__) && (!defined(_MSC_VER) || _MSC_VER<1600)
|
#if defined(_WIN32) && !defined(__MINGW32__) && \
|
||||||
|
(!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__)
|
||||||
#include <BaseTsd.h>
|
#include <BaseTsd.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
typedef __int8 int8_t;
|
typedef __int8 int8_t;
|
||||||
@@ -53,9 +54,16 @@ typedef unsigned __int64 uint64_t;
|
|||||||
# define HTTP_PARSER_STRICT 1
|
# define HTTP_PARSER_STRICT 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Maximium header size allowed */
|
/* Maximium header size allowed. If the macro is not defined
|
||||||
#define HTTP_MAX_HEADER_SIZE (80*1024)
|
* before including this header then the default is used. To
|
||||||
|
* change the maximum header size, define the macro in the build
|
||||||
|
* environment (e.g. -DHTTP_MAX_HEADER_SIZE=<value>). To remove
|
||||||
|
* the effective limit on the size of the header, define the macro
|
||||||
|
* to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff)
|
||||||
|
*/
|
||||||
|
#ifndef HTTP_MAX_HEADER_SIZE
|
||||||
|
# define HTTP_MAX_HEADER_SIZE (80*1024)
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct http_parser http_parser;
|
typedef struct http_parser http_parser;
|
||||||
typedef struct http_parser_settings http_parser_settings;
|
typedef struct http_parser_settings http_parser_settings;
|
||||||
@@ -70,7 +78,7 @@ typedef struct http_parser_settings http_parser_settings;
|
|||||||
* HEAD request which may contain 'Content-Length' or 'Transfer-Encoding:
|
* HEAD request which may contain 'Content-Length' or 'Transfer-Encoding:
|
||||||
* chunked' headers that indicate the presence of a body.
|
* chunked' headers that indicate the presence of a body.
|
||||||
*
|
*
|
||||||
* http_data_cb does not return data chunks. It will be call arbitrarally
|
* http_data_cb does not return data chunks. It will be called arbitrarily
|
||||||
* many times for each string. E.G. you might get 10 callbacks for "on_url"
|
* many times for each string. E.G. you might get 10 callbacks for "on_url"
|
||||||
* each providing just a few characters more data.
|
* each providing just a few characters more data.
|
||||||
*/
|
*/
|
||||||
@@ -89,7 +97,7 @@ typedef int (*http_cb) (http_parser*);
|
|||||||
XX(5, CONNECT, CONNECT) \
|
XX(5, CONNECT, CONNECT) \
|
||||||
XX(6, OPTIONS, OPTIONS) \
|
XX(6, OPTIONS, OPTIONS) \
|
||||||
XX(7, TRACE, TRACE) \
|
XX(7, TRACE, TRACE) \
|
||||||
/* webdav */ \
|
/* WebDAV */ \
|
||||||
XX(8, COPY, COPY) \
|
XX(8, COPY, COPY) \
|
||||||
XX(9, LOCK, LOCK) \
|
XX(9, LOCK, LOCK) \
|
||||||
XX(10, MKCOL, MKCOL) \
|
XX(10, MKCOL, MKCOL) \
|
||||||
@@ -98,19 +106,28 @@ typedef int (*http_cb) (http_parser*);
|
|||||||
XX(13, PROPPATCH, PROPPATCH) \
|
XX(13, PROPPATCH, PROPPATCH) \
|
||||||
XX(14, SEARCH, SEARCH) \
|
XX(14, SEARCH, SEARCH) \
|
||||||
XX(15, UNLOCK, UNLOCK) \
|
XX(15, UNLOCK, UNLOCK) \
|
||||||
|
XX(16, BIND, BIND) \
|
||||||
|
XX(17, REBIND, REBIND) \
|
||||||
|
XX(18, UNBIND, UNBIND) \
|
||||||
|
XX(19, ACL, ACL) \
|
||||||
/* subversion */ \
|
/* subversion */ \
|
||||||
XX(16, REPORT, REPORT) \
|
XX(20, REPORT, REPORT) \
|
||||||
XX(17, MKACTIVITY, MKACTIVITY) \
|
XX(21, MKACTIVITY, MKACTIVITY) \
|
||||||
XX(18, CHECKOUT, CHECKOUT) \
|
XX(22, CHECKOUT, CHECKOUT) \
|
||||||
XX(19, MERGE, MERGE) \
|
XX(23, MERGE, MERGE) \
|
||||||
/* upnp */ \
|
/* upnp */ \
|
||||||
XX(20, MSEARCH, M-SEARCH) \
|
XX(24, MSEARCH, M-SEARCH) \
|
||||||
XX(21, NOTIFY, NOTIFY) \
|
XX(25, NOTIFY, NOTIFY) \
|
||||||
XX(22, SUBSCRIBE, SUBSCRIBE) \
|
XX(26, SUBSCRIBE, SUBSCRIBE) \
|
||||||
XX(23, UNSUBSCRIBE, UNSUBSCRIBE) \
|
XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \
|
||||||
/* RFC-5789 */ \
|
/* RFC-5789 */ \
|
||||||
XX(24, PATCH, PATCH) \
|
XX(28, PATCH, PATCH) \
|
||||||
XX(25, PURGE, PURGE) \
|
XX(29, PURGE, PURGE) \
|
||||||
|
/* CalDAV */ \
|
||||||
|
XX(30, MKCALENDAR, MKCALENDAR) \
|
||||||
|
/* RFC-2068, section 19.6.1.2 */ \
|
||||||
|
XX(31, LINK, LINK) \
|
||||||
|
XX(32, UNLINK, UNLINK) \
|
||||||
|
|
||||||
enum http_method
|
enum http_method
|
||||||
{
|
{
|
||||||
@@ -128,9 +145,11 @@ enum flags
|
|||||||
{ F_CHUNKED = 1 << 0
|
{ F_CHUNKED = 1 << 0
|
||||||
, F_CONNECTION_KEEP_ALIVE = 1 << 1
|
, F_CONNECTION_KEEP_ALIVE = 1 << 1
|
||||||
, F_CONNECTION_CLOSE = 1 << 2
|
, F_CONNECTION_CLOSE = 1 << 2
|
||||||
, F_TRAILING = 1 << 3
|
, F_CONNECTION_UPGRADE = 1 << 3
|
||||||
, F_UPGRADE = 1 << 4
|
, F_TRAILING = 1 << 4
|
||||||
, F_SKIPBODY = 1 << 5
|
, F_UPGRADE = 1 << 5
|
||||||
|
, F_SKIPBODY = 1 << 6
|
||||||
|
, F_CONTENTLENGTH = 1 << 7
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -151,6 +170,8 @@ enum flags
|
|||||||
XX(CB_body, "the on_body callback failed") \
|
XX(CB_body, "the on_body callback failed") \
|
||||||
XX(CB_message_complete, "the on_message_complete callback failed") \
|
XX(CB_message_complete, "the on_message_complete callback failed") \
|
||||||
XX(CB_status, "the on_status callback failed") \
|
XX(CB_status, "the on_status callback failed") \
|
||||||
|
XX(CB_chunk_header, "the on_chunk_header callback failed") \
|
||||||
|
XX(CB_chunk_complete, "the on_chunk_complete callback failed") \
|
||||||
\
|
\
|
||||||
/* Parsing-related errors */ \
|
/* Parsing-related errors */ \
|
||||||
XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \
|
XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \
|
||||||
@@ -171,6 +192,8 @@ enum flags
|
|||||||
XX(INVALID_HEADER_TOKEN, "invalid character in header") \
|
XX(INVALID_HEADER_TOKEN, "invalid character in header") \
|
||||||
XX(INVALID_CONTENT_LENGTH, \
|
XX(INVALID_CONTENT_LENGTH, \
|
||||||
"invalid character in content-length header") \
|
"invalid character in content-length header") \
|
||||||
|
XX(UNEXPECTED_CONTENT_LENGTH, \
|
||||||
|
"unexpected content-length header") \
|
||||||
XX(INVALID_CHUNK_SIZE, \
|
XX(INVALID_CHUNK_SIZE, \
|
||||||
"invalid character in chunk size header") \
|
"invalid character in chunk size header") \
|
||||||
XX(INVALID_CONSTANT, "invalid constant string") \
|
XX(INVALID_CONSTANT, "invalid constant string") \
|
||||||
@@ -195,10 +218,11 @@ enum http_errno {
|
|||||||
struct http_parser {
|
struct http_parser {
|
||||||
/** PRIVATE **/
|
/** PRIVATE **/
|
||||||
unsigned int type : 2; /* enum http_parser_type */
|
unsigned int type : 2; /* enum http_parser_type */
|
||||||
unsigned int flags : 6; /* F_* values from 'flags' enum; semi-public */
|
unsigned int flags : 8; /* F_* values from 'flags' enum; semi-public */
|
||||||
unsigned int state : 8; /* enum state from http_parser.c */
|
unsigned int state : 7; /* enum state from http_parser.c */
|
||||||
unsigned int header_state : 8; /* enum header_state from http_parser.c */
|
unsigned int header_state : 7; /* enum header_state from http_parser.c */
|
||||||
unsigned int index : 8; /* index into current matcher */
|
unsigned int index : 7; /* index into current matcher */
|
||||||
|
unsigned int lenient_http_headers : 1;
|
||||||
|
|
||||||
uint32_t nread; /* # bytes read in various scenarios */
|
uint32_t nread; /* # bytes read in various scenarios */
|
||||||
uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */
|
uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */
|
||||||
@@ -231,6 +255,11 @@ struct http_parser_settings {
|
|||||||
http_cb on_headers_complete;
|
http_cb on_headers_complete;
|
||||||
http_data_cb on_body;
|
http_data_cb on_body;
|
||||||
http_cb on_message_complete;
|
http_cb on_message_complete;
|
||||||
|
/* When on_chunk_header is called, the current chunk length is stored
|
||||||
|
* in parser->content_length.
|
||||||
|
*/
|
||||||
|
http_cb on_chunk_header;
|
||||||
|
http_cb on_chunk_complete;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -272,13 +301,20 @@ struct http_parser_url {
|
|||||||
* unsigned major = (version >> 16) & 255;
|
* unsigned major = (version >> 16) & 255;
|
||||||
* unsigned minor = (version >> 8) & 255;
|
* unsigned minor = (version >> 8) & 255;
|
||||||
* unsigned patch = version & 255;
|
* unsigned patch = version & 255;
|
||||||
* printf("http_parser v%u.%u.%u\n", major, minor, version);
|
* printf("http_parser v%u.%u.%u\n", major, minor, patch);
|
||||||
*/
|
*/
|
||||||
unsigned long http_parser_version(void);
|
unsigned long http_parser_version(void);
|
||||||
|
|
||||||
void http_parser_init(http_parser *parser, enum http_parser_type type);
|
void http_parser_init(http_parser *parser, enum http_parser_type type);
|
||||||
|
|
||||||
|
|
||||||
|
/* Initialize http_parser_settings members to 0
|
||||||
|
*/
|
||||||
|
void http_parser_settings_init(http_parser_settings *settings);
|
||||||
|
|
||||||
|
|
||||||
|
/* Executes the parser. Returns number of parsed bytes. Sets
|
||||||
|
* `parser->http_errno` on error. */
|
||||||
size_t http_parser_execute(http_parser *parser,
|
size_t http_parser_execute(http_parser *parser,
|
||||||
const http_parser_settings *settings,
|
const http_parser_settings *settings,
|
||||||
const char *data,
|
const char *data,
|
||||||
@@ -302,6 +338,9 @@ const char *http_errno_name(enum http_errno err);
|
|||||||
/* Return a string description of the given error */
|
/* Return a string description of the given error */
|
||||||
const char *http_errno_description(enum http_errno err);
|
const char *http_errno_description(enum http_errno err);
|
||||||
|
|
||||||
|
/* Initialize all http_parser_url members to 0 */
|
||||||
|
void http_parser_url_init(struct http_parser_url *u);
|
||||||
|
|
||||||
/* Parse a URL; return nonzero on failure */
|
/* Parse a URL; return nonzero on failure */
|
||||||
int http_parser_parse_url(const char *buf, size_t buflen,
|
int http_parser_parse_url(const char *buf, size_t buflen,
|
||||||
int is_connect,
|
int is_connect,
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
#define MAX_HEADERS 13
|
#define MAX_HEADERS 13
|
||||||
#define MAX_ELEMENT_SIZE 2048
|
#define MAX_ELEMENT_SIZE 2048
|
||||||
|
#define MAX_CHUNKS 16
|
||||||
|
|
||||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||||
|
|
||||||
@@ -65,6 +66,10 @@ struct message {
|
|||||||
char headers [MAX_HEADERS][2][MAX_ELEMENT_SIZE];
|
char headers [MAX_HEADERS][2][MAX_ELEMENT_SIZE];
|
||||||
int should_keep_alive;
|
int should_keep_alive;
|
||||||
|
|
||||||
|
int num_chunks;
|
||||||
|
int num_chunks_complete;
|
||||||
|
int chunk_lengths[MAX_CHUNKS];
|
||||||
|
|
||||||
const char *upgrade; // upgraded body
|
const char *upgrade; // upgraded body
|
||||||
|
|
||||||
unsigned short http_major;
|
unsigned short http_major;
|
||||||
@@ -301,6 +306,8 @@ const struct message requests[] =
|
|||||||
{ { "Transfer-Encoding" , "chunked" }
|
{ { "Transfer-Encoding" , "chunked" }
|
||||||
}
|
}
|
||||||
,.body= "all your base are belong to us"
|
,.body= "all your base are belong to us"
|
||||||
|
,.num_chunks_complete= 2
|
||||||
|
,.chunk_lengths= { 0x1e }
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TWO_CHUNKS_MULT_ZERO_END 9
|
#define TWO_CHUNKS_MULT_ZERO_END 9
|
||||||
@@ -327,6 +334,8 @@ const struct message requests[] =
|
|||||||
{ { "Transfer-Encoding", "chunked" }
|
{ { "Transfer-Encoding", "chunked" }
|
||||||
}
|
}
|
||||||
,.body= "hello world"
|
,.body= "hello world"
|
||||||
|
,.num_chunks_complete= 3
|
||||||
|
,.chunk_lengths= { 5, 6 }
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHUNKED_W_TRAILING_HEADERS 10
|
#define CHUNKED_W_TRAILING_HEADERS 10
|
||||||
@@ -357,6 +366,8 @@ const struct message requests[] =
|
|||||||
, { "Content-Type", "text/plain" }
|
, { "Content-Type", "text/plain" }
|
||||||
}
|
}
|
||||||
,.body= "hello world"
|
,.body= "hello world"
|
||||||
|
,.num_chunks_complete= 3
|
||||||
|
,.chunk_lengths= { 5, 6 }
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHUNKED_W_BULLSHIT_AFTER_LENGTH 11
|
#define CHUNKED_W_BULLSHIT_AFTER_LENGTH 11
|
||||||
@@ -383,6 +394,8 @@ const struct message requests[] =
|
|||||||
{ { "Transfer-Encoding", "chunked" }
|
{ { "Transfer-Encoding", "chunked" }
|
||||||
}
|
}
|
||||||
,.body= "hello world"
|
,.body= "hello world"
|
||||||
|
,.num_chunks_complete= 3
|
||||||
|
,.chunk_lengths= { 5, 6 }
|
||||||
}
|
}
|
||||||
|
|
||||||
#define WITH_QUOTES 12
|
#define WITH_QUOTES 12
|
||||||
@@ -608,8 +621,14 @@ const struct message requests[] =
|
|||||||
" mno \r\n"
|
" mno \r\n"
|
||||||
"\t \tqrs\r\n"
|
"\t \tqrs\r\n"
|
||||||
"Line2: \t line2\t\r\n"
|
"Line2: \t line2\t\r\n"
|
||||||
|
"Line3:\r\n"
|
||||||
|
" line3\r\n"
|
||||||
|
"Line4: \r\n"
|
||||||
|
" \r\n"
|
||||||
|
"Connection:\r\n"
|
||||||
|
" close\r\n"
|
||||||
"\r\n"
|
"\r\n"
|
||||||
,.should_keep_alive= TRUE
|
,.should_keep_alive= FALSE
|
||||||
,.message_complete_on_eof= FALSE
|
,.message_complete_on_eof= FALSE
|
||||||
,.http_major= 1
|
,.http_major= 1
|
||||||
,.http_minor= 1
|
,.http_minor= 1
|
||||||
@@ -618,9 +637,12 @@ const struct message requests[] =
|
|||||||
,.fragment= ""
|
,.fragment= ""
|
||||||
,.request_path= "/"
|
,.request_path= "/"
|
||||||
,.request_url= "/"
|
,.request_url= "/"
|
||||||
,.num_headers= 2
|
,.num_headers= 5
|
||||||
,.headers= { { "Line1", "abcdefghijklmno qrs" }
|
,.headers= { { "Line1", "abc\tdef ghi\t\tjkl mno \t \tqrs" }
|
||||||
, { "Line2", "line2\t" }
|
, { "Line2", "line2\t" }
|
||||||
|
, { "Line3", "line3" }
|
||||||
|
, { "Line4", "" }
|
||||||
|
, { "Connection", "close" },
|
||||||
}
|
}
|
||||||
,.body= ""
|
,.body= ""
|
||||||
}
|
}
|
||||||
@@ -904,6 +926,232 @@ const struct message requests[] =
|
|||||||
,.body= ""
|
,.body= ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define LINE_FOLDING_IN_HEADER_WITH_LF 34
|
||||||
|
, {.name= "line folding in header value"
|
||||||
|
,.type= HTTP_REQUEST
|
||||||
|
,.raw= "GET / HTTP/1.1\n"
|
||||||
|
"Line1: abc\n"
|
||||||
|
"\tdef\n"
|
||||||
|
" ghi\n"
|
||||||
|
"\t\tjkl\n"
|
||||||
|
" mno \n"
|
||||||
|
"\t \tqrs\n"
|
||||||
|
"Line2: \t line2\t\n"
|
||||||
|
"Line3:\n"
|
||||||
|
" line3\n"
|
||||||
|
"Line4: \n"
|
||||||
|
" \n"
|
||||||
|
"Connection:\n"
|
||||||
|
" close\n"
|
||||||
|
"\n"
|
||||||
|
,.should_keep_alive= FALSE
|
||||||
|
,.message_complete_on_eof= FALSE
|
||||||
|
,.http_major= 1
|
||||||
|
,.http_minor= 1
|
||||||
|
,.method= HTTP_GET
|
||||||
|
,.query_string= ""
|
||||||
|
,.fragment= ""
|
||||||
|
,.request_path= "/"
|
||||||
|
,.request_url= "/"
|
||||||
|
,.num_headers= 5
|
||||||
|
,.headers= { { "Line1", "abc\tdef ghi\t\tjkl mno \t \tqrs" }
|
||||||
|
, { "Line2", "line2\t" }
|
||||||
|
, { "Line3", "line3" }
|
||||||
|
, { "Line4", "" }
|
||||||
|
, { "Connection", "close" },
|
||||||
|
}
|
||||||
|
,.body= ""
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CONNECTION_MULTI 35
|
||||||
|
, {.name = "multiple connection header values with folding"
|
||||||
|
,.type= HTTP_REQUEST
|
||||||
|
,.raw= "GET /demo HTTP/1.1\r\n"
|
||||||
|
"Host: example.com\r\n"
|
||||||
|
"Connection: Something,\r\n"
|
||||||
|
" Upgrade, ,Keep-Alive\r\n"
|
||||||
|
"Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n"
|
||||||
|
"Sec-WebSocket-Protocol: sample\r\n"
|
||||||
|
"Upgrade: WebSocket\r\n"
|
||||||
|
"Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n"
|
||||||
|
"Origin: http://example.com\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"Hot diggity dogg"
|
||||||
|
,.should_keep_alive= TRUE
|
||||||
|
,.message_complete_on_eof= FALSE
|
||||||
|
,.http_major= 1
|
||||||
|
,.http_minor= 1
|
||||||
|
,.method= HTTP_GET
|
||||||
|
,.query_string= ""
|
||||||
|
,.fragment= ""
|
||||||
|
,.request_path= "/demo"
|
||||||
|
,.request_url= "/demo"
|
||||||
|
,.num_headers= 7
|
||||||
|
,.upgrade="Hot diggity dogg"
|
||||||
|
,.headers= { { "Host", "example.com" }
|
||||||
|
, { "Connection", "Something, Upgrade, ,Keep-Alive" }
|
||||||
|
, { "Sec-WebSocket-Key2", "12998 5 Y3 1 .P00" }
|
||||||
|
, { "Sec-WebSocket-Protocol", "sample" }
|
||||||
|
, { "Upgrade", "WebSocket" }
|
||||||
|
, { "Sec-WebSocket-Key1", "4 @1 46546xW%0l 1 5" }
|
||||||
|
, { "Origin", "http://example.com" }
|
||||||
|
}
|
||||||
|
,.body= ""
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CONNECTION_MULTI_LWS 36
|
||||||
|
, {.name = "multiple connection header values with folding and lws"
|
||||||
|
,.type= HTTP_REQUEST
|
||||||
|
,.raw= "GET /demo HTTP/1.1\r\n"
|
||||||
|
"Connection: keep-alive, upgrade\r\n"
|
||||||
|
"Upgrade: WebSocket\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"Hot diggity dogg"
|
||||||
|
,.should_keep_alive= TRUE
|
||||||
|
,.message_complete_on_eof= FALSE
|
||||||
|
,.http_major= 1
|
||||||
|
,.http_minor= 1
|
||||||
|
,.method= HTTP_GET
|
||||||
|
,.query_string= ""
|
||||||
|
,.fragment= ""
|
||||||
|
,.request_path= "/demo"
|
||||||
|
,.request_url= "/demo"
|
||||||
|
,.num_headers= 2
|
||||||
|
,.upgrade="Hot diggity dogg"
|
||||||
|
,.headers= { { "Connection", "keep-alive, upgrade" }
|
||||||
|
, { "Upgrade", "WebSocket" }
|
||||||
|
}
|
||||||
|
,.body= ""
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CONNECTION_MULTI_LWS_CRLF 37
|
||||||
|
, {.name = "multiple connection header values with folding and lws"
|
||||||
|
,.type= HTTP_REQUEST
|
||||||
|
,.raw= "GET /demo HTTP/1.1\r\n"
|
||||||
|
"Connection: keep-alive, \r\n upgrade\r\n"
|
||||||
|
"Upgrade: WebSocket\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"Hot diggity dogg"
|
||||||
|
,.should_keep_alive= TRUE
|
||||||
|
,.message_complete_on_eof= FALSE
|
||||||
|
,.http_major= 1
|
||||||
|
,.http_minor= 1
|
||||||
|
,.method= HTTP_GET
|
||||||
|
,.query_string= ""
|
||||||
|
,.fragment= ""
|
||||||
|
,.request_path= "/demo"
|
||||||
|
,.request_url= "/demo"
|
||||||
|
,.num_headers= 2
|
||||||
|
,.upgrade="Hot diggity dogg"
|
||||||
|
,.headers= { { "Connection", "keep-alive, upgrade" }
|
||||||
|
, { "Upgrade", "WebSocket" }
|
||||||
|
}
|
||||||
|
,.body= ""
|
||||||
|
}
|
||||||
|
|
||||||
|
#define UPGRADE_POST_REQUEST 38
|
||||||
|
, {.name = "upgrade post request"
|
||||||
|
,.type= HTTP_REQUEST
|
||||||
|
,.raw= "POST /demo HTTP/1.1\r\n"
|
||||||
|
"Host: example.com\r\n"
|
||||||
|
"Connection: Upgrade\r\n"
|
||||||
|
"Upgrade: HTTP/2.0\r\n"
|
||||||
|
"Content-Length: 15\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"sweet post body"
|
||||||
|
"Hot diggity dogg"
|
||||||
|
,.should_keep_alive= TRUE
|
||||||
|
,.message_complete_on_eof= FALSE
|
||||||
|
,.http_major= 1
|
||||||
|
,.http_minor= 1
|
||||||
|
,.method= HTTP_POST
|
||||||
|
,.request_path= "/demo"
|
||||||
|
,.request_url= "/demo"
|
||||||
|
,.num_headers= 4
|
||||||
|
,.upgrade="Hot diggity dogg"
|
||||||
|
,.headers= { { "Host", "example.com" }
|
||||||
|
, { "Connection", "Upgrade" }
|
||||||
|
, { "Upgrade", "HTTP/2.0" }
|
||||||
|
, { "Content-Length", "15" }
|
||||||
|
}
|
||||||
|
,.body= "sweet post body"
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CONNECT_WITH_BODY_REQUEST 39
|
||||||
|
, {.name = "connect with body request"
|
||||||
|
,.type= HTTP_REQUEST
|
||||||
|
,.raw= "CONNECT foo.bar.com:443 HTTP/1.0\r\n"
|
||||||
|
"User-agent: Mozilla/1.1N\r\n"
|
||||||
|
"Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n"
|
||||||
|
"Content-Length: 10\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"blarfcicle"
|
||||||
|
,.should_keep_alive= FALSE
|
||||||
|
,.message_complete_on_eof= FALSE
|
||||||
|
,.http_major= 1
|
||||||
|
,.http_minor= 0
|
||||||
|
,.method= HTTP_CONNECT
|
||||||
|
,.request_url= "foo.bar.com:443"
|
||||||
|
,.num_headers= 3
|
||||||
|
,.upgrade="blarfcicle"
|
||||||
|
,.headers= { { "User-agent", "Mozilla/1.1N" }
|
||||||
|
, { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" }
|
||||||
|
, { "Content-Length", "10" }
|
||||||
|
}
|
||||||
|
,.body= ""
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Examples from the Internet draft for LINK/UNLINK methods:
|
||||||
|
* https://tools.ietf.org/id/draft-snell-link-method-01.html#rfc.section.5
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LINK_REQUEST 40
|
||||||
|
, {.name = "link request"
|
||||||
|
,.type= HTTP_REQUEST
|
||||||
|
,.raw= "LINK /images/my_dog.jpg HTTP/1.1\r\n"
|
||||||
|
"Host: example.com\r\n"
|
||||||
|
"Link: <http://example.com/profiles/joe>; rel=\"tag\"\r\n"
|
||||||
|
"Link: <http://example.com/profiles/sally>; rel=\"tag\"\r\n"
|
||||||
|
"\r\n"
|
||||||
|
,.should_keep_alive= TRUE
|
||||||
|
,.message_complete_on_eof= FALSE
|
||||||
|
,.http_major= 1
|
||||||
|
,.http_minor= 1
|
||||||
|
,.method= HTTP_LINK
|
||||||
|
,.request_path= "/images/my_dog.jpg"
|
||||||
|
,.request_url= "/images/my_dog.jpg"
|
||||||
|
,.query_string= ""
|
||||||
|
,.fragment= ""
|
||||||
|
,.num_headers= 3
|
||||||
|
,.headers= { { "Host", "example.com" }
|
||||||
|
, { "Link", "<http://example.com/profiles/joe>; rel=\"tag\"" }
|
||||||
|
, { "Link", "<http://example.com/profiles/sally>; rel=\"tag\"" }
|
||||||
|
}
|
||||||
|
,.body= ""
|
||||||
|
}
|
||||||
|
|
||||||
|
#define UNLINK_REQUEST 41
|
||||||
|
, {.name = "link request"
|
||||||
|
,.type= HTTP_REQUEST
|
||||||
|
,.raw= "UNLINK /images/my_dog.jpg HTTP/1.1\r\n"
|
||||||
|
"Host: example.com\r\n"
|
||||||
|
"Link: <http://example.com/profiles/sally>; rel=\"tag\"\r\n"
|
||||||
|
"\r\n"
|
||||||
|
,.should_keep_alive= TRUE
|
||||||
|
,.message_complete_on_eof= FALSE
|
||||||
|
,.http_major= 1
|
||||||
|
,.http_minor= 1
|
||||||
|
,.method= HTTP_UNLINK
|
||||||
|
,.request_path= "/images/my_dog.jpg"
|
||||||
|
,.request_url= "/images/my_dog.jpg"
|
||||||
|
,.query_string= ""
|
||||||
|
,.fragment= ""
|
||||||
|
,.num_headers= 2
|
||||||
|
,.headers= { { "Host", "example.com" }
|
||||||
|
, { "Link", "<http://example.com/profiles/sally>; rel=\"tag\"" }
|
||||||
|
}
|
||||||
|
,.body= ""
|
||||||
|
}
|
||||||
|
|
||||||
, {.name= NULL } /* sentinel */
|
, {.name= NULL } /* sentinel */
|
||||||
};
|
};
|
||||||
@@ -1064,7 +1312,8 @@ const struct message responses[] =
|
|||||||
,.body =
|
,.body =
|
||||||
"This is the data in the first chunk\r\n"
|
"This is the data in the first chunk\r\n"
|
||||||
"and this is the second one\r\n"
|
"and this is the second one\r\n"
|
||||||
|
,.num_chunks_complete= 3
|
||||||
|
,.chunk_lengths= { 0x25, 0x1c }
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NO_CARRIAGE_RET 5
|
#define NO_CARRIAGE_RET 5
|
||||||
@@ -1218,6 +1467,8 @@ const struct message responses[] =
|
|||||||
, { "Connection", "close" }
|
, { "Connection", "close" }
|
||||||
}
|
}
|
||||||
,.body= ""
|
,.body= ""
|
||||||
|
,.num_chunks_complete= 1
|
||||||
|
,.chunk_lengths= {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NON_ASCII_IN_STATUS_LINE 10
|
#define NON_ASCII_IN_STATUS_LINE 10
|
||||||
@@ -1400,6 +1651,7 @@ const struct message responses[] =
|
|||||||
}
|
}
|
||||||
,.body_size= 0
|
,.body_size= 0
|
||||||
,.body= ""
|
,.body= ""
|
||||||
|
,.num_chunks_complete= 1
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !HTTP_PARSER_STRICT
|
#if !HTTP_PARSER_STRICT
|
||||||
@@ -1473,6 +1725,8 @@ const struct message responses[] =
|
|||||||
, { "Transfer-Encoding", "chunked" }
|
, { "Transfer-Encoding", "chunked" }
|
||||||
}
|
}
|
||||||
,.body= "\n"
|
,.body= "\n"
|
||||||
|
,.num_chunks_complete= 2
|
||||||
|
,.chunk_lengths= { 1 }
|
||||||
}
|
}
|
||||||
|
|
||||||
#define EMPTY_REASON_PHRASE_AFTER_SPACE 20
|
#define EMPTY_REASON_PHRASE_AFTER_SPACE 20
|
||||||
@@ -1708,6 +1962,35 @@ response_status_cb (http_parser *p, const char *buf, size_t len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
chunk_header_cb (http_parser *p)
|
||||||
|
{
|
||||||
|
assert(p == parser);
|
||||||
|
int chunk_idx = messages[num_messages].num_chunks;
|
||||||
|
messages[num_messages].num_chunks++;
|
||||||
|
if (chunk_idx < MAX_CHUNKS) {
|
||||||
|
messages[num_messages].chunk_lengths[chunk_idx] = p->content_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
chunk_complete_cb (http_parser *p)
|
||||||
|
{
|
||||||
|
assert(p == parser);
|
||||||
|
|
||||||
|
/* Here we want to verify that each chunk_header_cb is matched by a
|
||||||
|
* chunk_complete_cb, so not only should the total number of calls to
|
||||||
|
* both callbacks be the same, but they also should be interleaved
|
||||||
|
* properly */
|
||||||
|
assert(messages[num_messages].num_chunks ==
|
||||||
|
messages[num_messages].num_chunks_complete + 1);
|
||||||
|
|
||||||
|
messages[num_messages].num_chunks_complete++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* These dontcall_* callbacks exist so that we can verify that when we're
|
/* These dontcall_* callbacks exist so that we can verify that when we're
|
||||||
* paused, no additional callbacks are invoked */
|
* paused, no additional callbacks are invoked */
|
||||||
int
|
int
|
||||||
@@ -1776,6 +2059,23 @@ dontcall_response_status_cb (http_parser *p, const char *buf, size_t len)
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dontcall_chunk_header_cb (http_parser *p)
|
||||||
|
{
|
||||||
|
if (p) { } // gcc
|
||||||
|
fprintf(stderr, "\n\n*** on_chunk_header() called on paused parser ***\n\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dontcall_chunk_complete_cb (http_parser *p)
|
||||||
|
{
|
||||||
|
if (p) { } // gcc
|
||||||
|
fprintf(stderr, "\n\n*** on_chunk_complete() "
|
||||||
|
"called on paused parser ***\n\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
static http_parser_settings settings_dontcall =
|
static http_parser_settings settings_dontcall =
|
||||||
{.on_message_begin = dontcall_message_begin_cb
|
{.on_message_begin = dontcall_message_begin_cb
|
||||||
,.on_header_field = dontcall_header_field_cb
|
,.on_header_field = dontcall_header_field_cb
|
||||||
@@ -1785,6 +2085,8 @@ static http_parser_settings settings_dontcall =
|
|||||||
,.on_body = dontcall_body_cb
|
,.on_body = dontcall_body_cb
|
||||||
,.on_headers_complete = dontcall_headers_complete_cb
|
,.on_headers_complete = dontcall_headers_complete_cb
|
||||||
,.on_message_complete = dontcall_message_complete_cb
|
,.on_message_complete = dontcall_message_complete_cb
|
||||||
|
,.on_chunk_header = dontcall_chunk_header_cb
|
||||||
|
,.on_chunk_complete = dontcall_chunk_complete_cb
|
||||||
};
|
};
|
||||||
|
|
||||||
/* These pause_* callbacks always pause the parser and just invoke the regular
|
/* These pause_* callbacks always pause the parser and just invoke the regular
|
||||||
@@ -1855,6 +2157,22 @@ pause_response_status_cb (http_parser *p, const char *buf, size_t len)
|
|||||||
return response_status_cb(p, buf, len);
|
return response_status_cb(p, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pause_chunk_header_cb (http_parser *p)
|
||||||
|
{
|
||||||
|
http_parser_pause(p, 1);
|
||||||
|
*current_pause_parser = settings_dontcall;
|
||||||
|
return chunk_header_cb(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pause_chunk_complete_cb (http_parser *p)
|
||||||
|
{
|
||||||
|
http_parser_pause(p, 1);
|
||||||
|
*current_pause_parser = settings_dontcall;
|
||||||
|
return chunk_complete_cb(p);
|
||||||
|
}
|
||||||
|
|
||||||
static http_parser_settings settings_pause =
|
static http_parser_settings settings_pause =
|
||||||
{.on_message_begin = pause_message_begin_cb
|
{.on_message_begin = pause_message_begin_cb
|
||||||
,.on_header_field = pause_header_field_cb
|
,.on_header_field = pause_header_field_cb
|
||||||
@@ -1864,6 +2182,8 @@ static http_parser_settings settings_pause =
|
|||||||
,.on_body = pause_body_cb
|
,.on_body = pause_body_cb
|
||||||
,.on_headers_complete = pause_headers_complete_cb
|
,.on_headers_complete = pause_headers_complete_cb
|
||||||
,.on_message_complete = pause_message_complete_cb
|
,.on_message_complete = pause_message_complete_cb
|
||||||
|
,.on_chunk_header = pause_chunk_header_cb
|
||||||
|
,.on_chunk_complete = pause_chunk_complete_cb
|
||||||
};
|
};
|
||||||
|
|
||||||
static http_parser_settings settings =
|
static http_parser_settings settings =
|
||||||
@@ -1875,6 +2195,8 @@ static http_parser_settings settings =
|
|||||||
,.on_body = body_cb
|
,.on_body = body_cb
|
||||||
,.on_headers_complete = headers_complete_cb
|
,.on_headers_complete = headers_complete_cb
|
||||||
,.on_message_complete = message_complete_cb
|
,.on_message_complete = message_complete_cb
|
||||||
|
,.on_chunk_header = chunk_header_cb
|
||||||
|
,.on_chunk_complete = chunk_complete_cb
|
||||||
};
|
};
|
||||||
|
|
||||||
static http_parser_settings settings_count_body =
|
static http_parser_settings settings_count_body =
|
||||||
@@ -1886,6 +2208,8 @@ static http_parser_settings settings_count_body =
|
|||||||
,.on_body = count_body_cb
|
,.on_body = count_body_cb
|
||||||
,.on_headers_complete = headers_complete_cb
|
,.on_headers_complete = headers_complete_cb
|
||||||
,.on_message_complete = message_complete_cb
|
,.on_message_complete = message_complete_cb
|
||||||
|
,.on_chunk_header = chunk_header_cb
|
||||||
|
,.on_chunk_complete = chunk_complete_cb
|
||||||
};
|
};
|
||||||
|
|
||||||
static http_parser_settings settings_null =
|
static http_parser_settings settings_null =
|
||||||
@@ -1897,6 +2221,8 @@ static http_parser_settings settings_null =
|
|||||||
,.on_body = 0
|
,.on_body = 0
|
||||||
,.on_headers_complete = 0
|
,.on_headers_complete = 0
|
||||||
,.on_message_complete = 0
|
,.on_message_complete = 0
|
||||||
|
,.on_chunk_header = 0
|
||||||
|
,.on_chunk_complete = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -2065,6 +2391,12 @@ message_eq (int index, const struct message *expected)
|
|||||||
MESSAGE_CHECK_STR_EQ(expected, m, body);
|
MESSAGE_CHECK_STR_EQ(expected, m, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(m->num_chunks == m->num_chunks_complete);
|
||||||
|
MESSAGE_CHECK_NUM_EQ(expected, m, num_chunks_complete);
|
||||||
|
for (i = 0; i < m->num_chunks && i < MAX_CHUNKS; i++) {
|
||||||
|
MESSAGE_CHECK_NUM_EQ(expected, m, chunk_lengths[i]);
|
||||||
|
}
|
||||||
|
|
||||||
MESSAGE_CHECK_NUM_EQ(expected, m, num_headers);
|
MESSAGE_CHECK_NUM_EQ(expected, m, num_headers);
|
||||||
|
|
||||||
int r;
|
int r;
|
||||||
@@ -2112,7 +2444,7 @@ upgrade_message_fix(char *body, const size_t nread, const size_t nmsgs, ...) {
|
|||||||
va_list ap;
|
va_list ap;
|
||||||
size_t i;
|
size_t i;
|
||||||
size_t off = 0;
|
size_t off = 0;
|
||||||
|
|
||||||
va_start(ap, nmsgs);
|
va_start(ap, nmsgs);
|
||||||
|
|
||||||
for (i = 0; i < nmsgs; i++) {
|
for (i = 0; i < nmsgs; i++) {
|
||||||
@@ -2161,7 +2493,6 @@ print_error (const char *raw, size_t error_location)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '\n':
|
case '\n':
|
||||||
char_len = 2;
|
|
||||||
fprintf(stderr, "\\n\n");
|
fprintf(stderr, "\\n\n");
|
||||||
|
|
||||||
if (this_line) goto print;
|
if (this_line) goto print;
|
||||||
@@ -2639,6 +2970,59 @@ const struct url_test url_tests[] =
|
|||||||
,.rv=1 /* s_dead */
|
,.rv=1 /* s_dead */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
, {.name="ipv6 address with Zone ID"
|
||||||
|
,.url="http://[fe80::a%25eth0]/"
|
||||||
|
,.is_connect=0
|
||||||
|
,.u=
|
||||||
|
{.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH)
|
||||||
|
,.port=0
|
||||||
|
,.field_data=
|
||||||
|
{{ 0, 4 } /* UF_SCHEMA */
|
||||||
|
,{ 8, 14 } /* UF_HOST */
|
||||||
|
,{ 0, 0 } /* UF_PORT */
|
||||||
|
,{ 23, 1 } /* UF_PATH */
|
||||||
|
,{ 0, 0 } /* UF_QUERY */
|
||||||
|
,{ 0, 0 } /* UF_FRAGMENT */
|
||||||
|
,{ 0, 0 } /* UF_USERINFO */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
,.rv=0
|
||||||
|
}
|
||||||
|
|
||||||
|
, {.name="ipv6 address with Zone ID, but '%' is not percent-encoded"
|
||||||
|
,.url="http://[fe80::a%eth0]/"
|
||||||
|
,.is_connect=0
|
||||||
|
,.u=
|
||||||
|
{.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH)
|
||||||
|
,.port=0
|
||||||
|
,.field_data=
|
||||||
|
{{ 0, 4 } /* UF_SCHEMA */
|
||||||
|
,{ 8, 12 } /* UF_HOST */
|
||||||
|
,{ 0, 0 } /* UF_PORT */
|
||||||
|
,{ 21, 1 } /* UF_PATH */
|
||||||
|
,{ 0, 0 } /* UF_QUERY */
|
||||||
|
,{ 0, 0 } /* UF_FRAGMENT */
|
||||||
|
,{ 0, 0 } /* UF_USERINFO */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
,.rv=0
|
||||||
|
}
|
||||||
|
|
||||||
|
, {.name="ipv6 address ending with '%'"
|
||||||
|
,.url="http://[fe80::a%]/"
|
||||||
|
,.rv=1 /* s_dead */
|
||||||
|
}
|
||||||
|
|
||||||
|
, {.name="ipv6 address with Zone ID including bad character"
|
||||||
|
,.url="http://[fe80::a%$HOME]/"
|
||||||
|
,.rv=1 /* s_dead */
|
||||||
|
}
|
||||||
|
|
||||||
|
, {.name="just ipv6 Zone ID"
|
||||||
|
,.url="http://[%eth0]/"
|
||||||
|
,.rv=1 /* s_dead */
|
||||||
|
}
|
||||||
|
|
||||||
#if HTTP_PARSER_STRICT
|
#if HTTP_PARSER_STRICT
|
||||||
|
|
||||||
, {.name="tab in URL"
|
, {.name="tab in URL"
|
||||||
@@ -2779,7 +3163,7 @@ test_message (const struct message *message)
|
|||||||
if (msg1len) {
|
if (msg1len) {
|
||||||
read = parse(msg1, msg1len);
|
read = parse(msg1, msg1len);
|
||||||
|
|
||||||
if (message->upgrade && parser->upgrade) {
|
if (message->upgrade && parser->upgrade && num_messages > 0) {
|
||||||
messages[num_messages - 1].upgrade = msg1 + read;
|
messages[num_messages - 1].upgrade = msg1 + read;
|
||||||
goto test;
|
goto test;
|
||||||
}
|
}
|
||||||
@@ -2864,15 +3248,11 @@ test_simple (const char *buf, enum http_errno err_expected)
|
|||||||
{
|
{
|
||||||
parser_init(HTTP_REQUEST);
|
parser_init(HTTP_REQUEST);
|
||||||
|
|
||||||
size_t parsed;
|
|
||||||
int pass;
|
|
||||||
enum http_errno err;
|
enum http_errno err;
|
||||||
|
|
||||||
parsed = parse(buf, strlen(buf));
|
parse(buf, strlen(buf));
|
||||||
pass = (parsed == strlen(buf));
|
|
||||||
err = HTTP_PARSER_ERRNO(parser);
|
err = HTTP_PARSER_ERRNO(parser);
|
||||||
parsed = parse(NULL, 0);
|
parse(NULL, 0);
|
||||||
pass &= (parsed == 0);
|
|
||||||
|
|
||||||
parser_free();
|
parser_free();
|
||||||
|
|
||||||
@@ -2890,6 +3270,155 @@ test_simple (const char *buf, enum http_errno err_expected)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_invalid_header_content (int req, const char* str)
|
||||||
|
{
|
||||||
|
http_parser parser;
|
||||||
|
http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE);
|
||||||
|
size_t parsed;
|
||||||
|
const char *buf;
|
||||||
|
buf = req ?
|
||||||
|
"GET / HTTP/1.1\r\n" :
|
||||||
|
"HTTP/1.1 200 OK\r\n";
|
||||||
|
parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf));
|
||||||
|
assert(parsed == strlen(buf));
|
||||||
|
|
||||||
|
buf = str;
|
||||||
|
size_t buflen = strlen(buf);
|
||||||
|
|
||||||
|
parsed = http_parser_execute(&parser, &settings_null, buf, buflen);
|
||||||
|
if (parsed != buflen) {
|
||||||
|
assert(HTTP_PARSER_ERRNO(&parser) == HPE_INVALID_HEADER_TOKEN);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
"\n*** Error expected but none in invalid header content test ***\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_invalid_header_field_content_error (int req)
|
||||||
|
{
|
||||||
|
test_invalid_header_content(req, "Foo: F\01ailure");
|
||||||
|
test_invalid_header_content(req, "Foo: B\02ar");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_invalid_header_field (int req, const char* str)
|
||||||
|
{
|
||||||
|
http_parser parser;
|
||||||
|
http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE);
|
||||||
|
size_t parsed;
|
||||||
|
const char *buf;
|
||||||
|
buf = req ?
|
||||||
|
"GET / HTTP/1.1\r\n" :
|
||||||
|
"HTTP/1.1 200 OK\r\n";
|
||||||
|
parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf));
|
||||||
|
assert(parsed == strlen(buf));
|
||||||
|
|
||||||
|
buf = str;
|
||||||
|
size_t buflen = strlen(buf);
|
||||||
|
|
||||||
|
parsed = http_parser_execute(&parser, &settings_null, buf, buflen);
|
||||||
|
if (parsed != buflen) {
|
||||||
|
assert(HTTP_PARSER_ERRNO(&parser) == HPE_INVALID_HEADER_TOKEN);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
"\n*** Error expected but none in invalid header token test ***\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_invalid_header_field_token_error (int req)
|
||||||
|
{
|
||||||
|
test_invalid_header_field(req, "Fo@: Failure");
|
||||||
|
test_invalid_header_field(req, "Foo\01\test: Bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_double_content_length_error (int req)
|
||||||
|
{
|
||||||
|
http_parser parser;
|
||||||
|
http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE);
|
||||||
|
size_t parsed;
|
||||||
|
const char *buf;
|
||||||
|
buf = req ?
|
||||||
|
"GET / HTTP/1.1\r\n" :
|
||||||
|
"HTTP/1.1 200 OK\r\n";
|
||||||
|
parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf));
|
||||||
|
assert(parsed == strlen(buf));
|
||||||
|
|
||||||
|
buf = "Content-Length: 0\r\nContent-Length: 1\r\n\r\n";
|
||||||
|
size_t buflen = strlen(buf);
|
||||||
|
|
||||||
|
parsed = http_parser_execute(&parser, &settings_null, buf, buflen);
|
||||||
|
if (parsed != buflen) {
|
||||||
|
assert(HTTP_PARSER_ERRNO(&parser) == HPE_UNEXPECTED_CONTENT_LENGTH);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
"\n*** Error expected but none in double content-length test ***\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_chunked_content_length_error (int req)
|
||||||
|
{
|
||||||
|
http_parser parser;
|
||||||
|
http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE);
|
||||||
|
size_t parsed;
|
||||||
|
const char *buf;
|
||||||
|
buf = req ?
|
||||||
|
"GET / HTTP/1.1\r\n" :
|
||||||
|
"HTTP/1.1 200 OK\r\n";
|
||||||
|
parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf));
|
||||||
|
assert(parsed == strlen(buf));
|
||||||
|
|
||||||
|
buf = "Transfer-Encoding: chunked\r\nContent-Length: 1\r\n\r\n";
|
||||||
|
size_t buflen = strlen(buf);
|
||||||
|
|
||||||
|
parsed = http_parser_execute(&parser, &settings_null, buf, buflen);
|
||||||
|
if (parsed != buflen) {
|
||||||
|
assert(HTTP_PARSER_ERRNO(&parser) == HPE_UNEXPECTED_CONTENT_LENGTH);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
"\n*** Error expected but none in chunked content-length test ***\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_header_cr_no_lf_error (int req)
|
||||||
|
{
|
||||||
|
http_parser parser;
|
||||||
|
http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE);
|
||||||
|
size_t parsed;
|
||||||
|
const char *buf;
|
||||||
|
buf = req ?
|
||||||
|
"GET / HTTP/1.1\r\n" :
|
||||||
|
"HTTP/1.1 200 OK\r\n";
|
||||||
|
parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf));
|
||||||
|
assert(parsed == strlen(buf));
|
||||||
|
|
||||||
|
buf = "Foo: 1\rBar: 1\r\n\r\n";
|
||||||
|
size_t buflen = strlen(buf);
|
||||||
|
|
||||||
|
parsed = http_parser_execute(&parser, &settings_null, buf, buflen);
|
||||||
|
if (parsed != buflen) {
|
||||||
|
assert(HTTP_PARSER_ERRNO(&parser) == HPE_LF_EXPECTED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
"\n*** Error expected but none in header whitespace test ***\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_header_overflow_error (int req)
|
test_header_overflow_error (int req)
|
||||||
{
|
{
|
||||||
@@ -2918,6 +3447,22 @@ test_header_overflow_error (int req)
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
test_header_nread_value ()
|
||||||
|
{
|
||||||
|
http_parser parser;
|
||||||
|
http_parser_init(&parser, HTTP_REQUEST);
|
||||||
|
size_t parsed;
|
||||||
|
const char *buf;
|
||||||
|
buf = "GET / HTTP/1.1\r\nheader: value\nhdr: value\r\n";
|
||||||
|
parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf));
|
||||||
|
assert(parsed == strlen(buf));
|
||||||
|
|
||||||
|
assert(parser.nread == strlen(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_content_length_overflow (const char *buf, size_t buflen, int expect_ok)
|
test_content_length_overflow (const char *buf, size_t buflen, int expect_ok)
|
||||||
{
|
{
|
||||||
@@ -3284,6 +3829,9 @@ main (void)
|
|||||||
test_parse_url();
|
test_parse_url();
|
||||||
test_method_str();
|
test_method_str();
|
||||||
|
|
||||||
|
//// NREAD
|
||||||
|
test_header_nread_value();
|
||||||
|
|
||||||
//// OVERFLOW CONDITIONS
|
//// OVERFLOW CONDITIONS
|
||||||
|
|
||||||
test_header_overflow_error(HTTP_REQUEST);
|
test_header_overflow_error(HTTP_REQUEST);
|
||||||
@@ -3297,6 +3845,18 @@ main (void)
|
|||||||
test_header_content_length_overflow_error();
|
test_header_content_length_overflow_error();
|
||||||
test_chunk_content_length_overflow_error();
|
test_chunk_content_length_overflow_error();
|
||||||
|
|
||||||
|
//// HEADER FIELD CONDITIONS
|
||||||
|
test_double_content_length_error(HTTP_REQUEST);
|
||||||
|
test_chunked_content_length_error(HTTP_REQUEST);
|
||||||
|
test_header_cr_no_lf_error(HTTP_REQUEST);
|
||||||
|
test_invalid_header_field_token_error(HTTP_REQUEST);
|
||||||
|
test_invalid_header_field_content_error(HTTP_REQUEST);
|
||||||
|
test_double_content_length_error(HTTP_RESPONSE);
|
||||||
|
test_chunked_content_length_error(HTTP_RESPONSE);
|
||||||
|
test_header_cr_no_lf_error(HTTP_RESPONSE);
|
||||||
|
test_invalid_header_field_token_error(HTTP_RESPONSE);
|
||||||
|
test_invalid_header_field_content_error(HTTP_RESPONSE);
|
||||||
|
|
||||||
//// RESPONSES
|
//// RESPONSES
|
||||||
|
|
||||||
for (i = 0; i < response_count; i++) {
|
for (i = 0; i < response_count; i++) {
|
||||||
@@ -3343,7 +3903,11 @@ main (void)
|
|||||||
, { "Content-Type", "text/plain" }
|
, { "Content-Type", "text/plain" }
|
||||||
}
|
}
|
||||||
,.body_size= 31337*1024
|
,.body_size= 31337*1024
|
||||||
|
,.num_chunks_complete= 31338
|
||||||
};
|
};
|
||||||
|
for (i = 0; i < MAX_CHUNKS; i++) {
|
||||||
|
large_chunked.chunk_lengths[i] = 1024;
|
||||||
|
}
|
||||||
test_message_count_body(&large_chunked);
|
test_message_count_body(&large_chunked);
|
||||||
free(msg);
|
free(msg);
|
||||||
}
|
}
|
||||||
@@ -3392,7 +3956,12 @@ main (void)
|
|||||||
"MOVE",
|
"MOVE",
|
||||||
"PROPFIND",
|
"PROPFIND",
|
||||||
"PROPPATCH",
|
"PROPPATCH",
|
||||||
|
"SEARCH",
|
||||||
"UNLOCK",
|
"UNLOCK",
|
||||||
|
"BIND",
|
||||||
|
"REBIND",
|
||||||
|
"UNBIND",
|
||||||
|
"ACL",
|
||||||
"REPORT",
|
"REPORT",
|
||||||
"MKACTIVITY",
|
"MKACTIVITY",
|
||||||
"CHECKOUT",
|
"CHECKOUT",
|
||||||
@@ -3402,6 +3971,10 @@ main (void)
|
|||||||
"SUBSCRIBE",
|
"SUBSCRIBE",
|
||||||
"UNSUBSCRIBE",
|
"UNSUBSCRIBE",
|
||||||
"PATCH",
|
"PATCH",
|
||||||
|
"PURGE",
|
||||||
|
"MKCALENDAR",
|
||||||
|
"LINK",
|
||||||
|
"UNLINK",
|
||||||
0 };
|
0 };
|
||||||
const char **this_method;
|
const char **this_method;
|
||||||
for (this_method = all_methods; *this_method; this_method++) {
|
for (this_method = all_methods; *this_method; this_method++) {
|
||||||
@@ -3430,6 +4003,13 @@ main (void)
|
|||||||
test_simple(buf, HPE_INVALID_METHOD);
|
test_simple(buf, HPE_INVALID_METHOD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// illegal header field name line folding
|
||||||
|
test_simple("GET / HTTP/1.1\r\n"
|
||||||
|
"name\r\n"
|
||||||
|
" : value\r\n"
|
||||||
|
"\r\n",
|
||||||
|
HPE_INVALID_HEADER_TOKEN);
|
||||||
|
|
||||||
const char *dumbfuck2 =
|
const char *dumbfuck2 =
|
||||||
"GET / HTTP/1.1\r\n"
|
"GET / HTTP/1.1\r\n"
|
||||||
"X-SSL-Bullshit: -----BEGIN CERTIFICATE-----\r\n"
|
"X-SSL-Bullshit: -----BEGIN CERTIFICATE-----\r\n"
|
||||||
@@ -3467,6 +4047,22 @@ main (void)
|
|||||||
"\r\n";
|
"\r\n";
|
||||||
test_simple(dumbfuck2, HPE_OK);
|
test_simple(dumbfuck2, HPE_OK);
|
||||||
|
|
||||||
|
const char *corrupted_connection =
|
||||||
|
"GET / HTTP/1.1\r\n"
|
||||||
|
"Host: www.example.com\r\n"
|
||||||
|
"Connection\r\033\065\325eep-Alive\r\n"
|
||||||
|
"Accept-Encoding: gzip\r\n"
|
||||||
|
"\r\n";
|
||||||
|
test_simple(corrupted_connection, HPE_INVALID_HEADER_TOKEN);
|
||||||
|
|
||||||
|
const char *corrupted_header_name =
|
||||||
|
"GET / HTTP/1.1\r\n"
|
||||||
|
"Host: www.example.com\r\n"
|
||||||
|
"X-Some-Header\r\033\065\325eep-Alive\r\n"
|
||||||
|
"Accept-Encoding: gzip\r\n"
|
||||||
|
"\r\n";
|
||||||
|
test_simple(corrupted_header_name, HPE_INVALID_HEADER_TOKEN);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// NOTE(Wed Nov 18 11:57:27 CET 2009) this seems okay. we just read body
|
// NOTE(Wed Nov 18 11:57:27 CET 2009) this seems okay. we just read body
|
||||||
// until EOF.
|
// until EOF.
|
||||||
|
|||||||
@@ -83,6 +83,10 @@ convert_http_method (joyent::http_method m)
|
|||||||
case HTTP_PROPPATCH: return http::method_t::http_proppatch;
|
case HTTP_PROPPATCH: return http::method_t::http_proppatch;
|
||||||
case HTTP_SEARCH: return http::method_t::http_search;
|
case HTTP_SEARCH: return http::method_t::http_search;
|
||||||
case HTTP_UNLOCK: return http::method_t::http_unlock;
|
case HTTP_UNLOCK: return http::method_t::http_unlock;
|
||||||
|
case HTTP_BIND: return http::method_t::http_bind;
|
||||||
|
case HTTP_REBIND: return http::method_t::http_rebind;
|
||||||
|
case HTTP_UNBIND: return http::method_t::http_unbind;
|
||||||
|
case HTTP_ACL: return http::method_t::http_acl;
|
||||||
|
|
||||||
// subversion
|
// subversion
|
||||||
case HTTP_REPORT: return http::method_t::http_report;
|
case HTTP_REPORT: return http::method_t::http_report;
|
||||||
@@ -99,6 +103,13 @@ convert_http_method (joyent::http_method m)
|
|||||||
// RFC-5789
|
// RFC-5789
|
||||||
case HTTP_PATCH: return http::method_t::http_patch;
|
case HTTP_PATCH: return http::method_t::http_patch;
|
||||||
case HTTP_PURGE: return http::method_t::http_purge;
|
case HTTP_PURGE: return http::method_t::http_purge;
|
||||||
|
|
||||||
|
// CalDav
|
||||||
|
case HTTP_MKCALENDAR: return http::method_t::http_mkcalendar;
|
||||||
|
|
||||||
|
// RFC-2068, section 19.6.1.2
|
||||||
|
case HTTP_LINK: return http::method_t::http_link;
|
||||||
|
case HTTP_UNLINK: return http::method_t::http_unlink;
|
||||||
};
|
};
|
||||||
|
|
||||||
return http::method_t::http_get;
|
return http::method_t::http_get;
|
||||||
|
|||||||
@@ -1,292 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#include <beast/http/raw_parser.h>
|
|
||||||
|
|
||||||
#include <beast/http/impl/joyent_parser.h>
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
namespace http {
|
|
||||||
|
|
||||||
raw_parser::raw_parser (callback& cb)
|
|
||||||
: m_cb (cb)
|
|
||||||
{
|
|
||||||
static_assert (sizeof(joyent::http_parser) == sizeof(state_t),
|
|
||||||
"state_t size must match http_parser size");
|
|
||||||
|
|
||||||
static_assert (sizeof(joyent::http_parser_settings) == sizeof(hooks_t),
|
|
||||||
"hooks_t size must match http_parser_settings size");
|
|
||||||
|
|
||||||
auto s (reinterpret_cast <joyent::http_parser*> (&m_state));
|
|
||||||
s->data = this;
|
|
||||||
|
|
||||||
auto h (reinterpret_cast <joyent::http_parser_settings*> (&m_hooks));
|
|
||||||
h->on_message_begin = &raw_parser::on_message_start;
|
|
||||||
h->on_url = &raw_parser::on_url;
|
|
||||||
h->on_status = &raw_parser::on_status;
|
|
||||||
h->on_header_field = &raw_parser::on_header_field;
|
|
||||||
h->on_header_value = &raw_parser::on_header_value;
|
|
||||||
h->on_headers_complete = &raw_parser::on_headers_done;
|
|
||||||
h->on_body = &raw_parser::on_body;
|
|
||||||
h->on_message_complete = &raw_parser::on_message_complete;
|
|
||||||
}
|
|
||||||
|
|
||||||
raw_parser::~raw_parser()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
raw_parser::reset (message_type type)
|
|
||||||
{
|
|
||||||
auto s (reinterpret_cast <joyent::http_parser*> (&m_state));
|
|
||||||
http_parser_init (s, (type == request)
|
|
||||||
? joyent::HTTP_REQUEST : joyent::HTTP_RESPONSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto
|
|
||||||
raw_parser::process_data (void const* buf, std::size_t bytes) ->
|
|
||||||
std::pair <error_code, std::size_t>
|
|
||||||
{
|
|
||||||
auto s (reinterpret_cast <joyent::http_parser*> (&m_state));
|
|
||||||
auto h (reinterpret_cast <joyent::http_parser_settings const*> (&m_hooks));
|
|
||||||
std::size_t const bytes_used (joyent::http_parser_execute (s, h,
|
|
||||||
static_cast <const char*> (buf), bytes));
|
|
||||||
return std::make_pair (m_ec, bytes_used);;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto
|
|
||||||
raw_parser::process_eof () ->
|
|
||||||
error_code
|
|
||||||
{
|
|
||||||
auto s (reinterpret_cast <joyent::http_parser*> (&m_state));
|
|
||||||
auto h (reinterpret_cast <joyent::http_parser_settings const*> (&m_hooks));
|
|
||||||
joyent::http_parser_execute (s, h, nullptr, 0);
|
|
||||||
return m_ec;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
int
|
|
||||||
raw_parser::do_message_start ()
|
|
||||||
{
|
|
||||||
auto const p (reinterpret_cast <joyent::http_parser const*> (&m_state));
|
|
||||||
if (p->type == joyent::HTTP_REQUEST)
|
|
||||||
m_ec = m_cb.get().on_request ();
|
|
||||||
else if (p->type == joyent::HTTP_RESPONSE)
|
|
||||||
m_ec = m_cb.get().on_response ();
|
|
||||||
return m_ec ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
raw_parser::do_url (char const* in, std::size_t bytes)
|
|
||||||
{
|
|
||||||
m_ec = m_cb.get().on_url (in, bytes);
|
|
||||||
return m_ec ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
raw_parser::do_status (char const* in, std::size_t bytes)
|
|
||||||
{
|
|
||||||
auto const p (reinterpret_cast <joyent::http_parser const*> (&m_state));
|
|
||||||
m_ec = m_cb.get().on_status (p->status_code, in, bytes);
|
|
||||||
return m_ec ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
raw_parser::do_header_field (char const* in, std::size_t bytes)
|
|
||||||
{
|
|
||||||
m_ec = m_cb.get().on_header_field (in, bytes);
|
|
||||||
return m_ec ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
raw_parser::do_header_value (char const* in, std::size_t bytes)
|
|
||||||
{
|
|
||||||
m_ec = m_cb.get().on_header_value (in, bytes);
|
|
||||||
return m_ec ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
raw_parser::do_headers_done ()
|
|
||||||
{
|
|
||||||
auto const p (reinterpret_cast <joyent::http_parser const*> (&m_state));
|
|
||||||
bool const keep_alive (joyent::http_should_keep_alive (p) != 0);
|
|
||||||
m_ec = m_cb.get().on_headers_done (keep_alive);
|
|
||||||
return m_ec ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
raw_parser::do_body (char const* in, std::size_t bytes)
|
|
||||||
{
|
|
||||||
auto const p (reinterpret_cast <joyent::http_parser const*> (&m_state));
|
|
||||||
bool const is_final (
|
|
||||||
joyent::http_body_is_final (p) != 0);
|
|
||||||
m_ec = m_cb.get().on_body (is_final, in, bytes);
|
|
||||||
return m_ec ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
raw_parser::do_message_complete ()
|
|
||||||
{
|
|
||||||
auto const p (reinterpret_cast <joyent::http_parser const*> (&m_state));
|
|
||||||
bool const keep_alive (joyent::http_should_keep_alive (p) != 0);
|
|
||||||
m_ec = m_cb.get().on_message_complete (keep_alive);
|
|
||||||
return m_ec ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
int
|
|
||||||
raw_parser::on_message_start (joyent::http_parser* p)
|
|
||||||
{
|
|
||||||
return reinterpret_cast <raw_parser*> (
|
|
||||||
p->data)->do_message_start();
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
raw_parser::on_url (joyent::http_parser* p,
|
|
||||||
char const* in, std::size_t bytes)
|
|
||||||
{
|
|
||||||
return reinterpret_cast <raw_parser*> (
|
|
||||||
p->data)->do_url (in, bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
raw_parser::on_status (joyent::http_parser* p,
|
|
||||||
char const* in, std::size_t bytes)
|
|
||||||
{
|
|
||||||
return reinterpret_cast <raw_parser*> (
|
|
||||||
p->data)->do_status (in, bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
raw_parser::on_header_field (joyent::http_parser* p,
|
|
||||||
char const* in, std::size_t bytes)
|
|
||||||
{
|
|
||||||
return reinterpret_cast <raw_parser*> (
|
|
||||||
p->data)->do_header_field (in, bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
raw_parser::on_header_value (joyent::http_parser* p,
|
|
||||||
char const* in, std::size_t bytes)
|
|
||||||
{
|
|
||||||
return reinterpret_cast <raw_parser*> (
|
|
||||||
p->data)->do_header_value (in, bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
raw_parser::on_headers_done (joyent::http_parser* p)
|
|
||||||
{
|
|
||||||
return reinterpret_cast <raw_parser*> (
|
|
||||||
p->data)->do_headers_done();
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
raw_parser::on_body (joyent::http_parser* p,
|
|
||||||
char const* in, std::size_t bytes)
|
|
||||||
{
|
|
||||||
return reinterpret_cast <raw_parser*> (
|
|
||||||
p->data)->do_body (
|
|
||||||
in, bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
raw_parser::on_message_complete (joyent::http_parser* p)
|
|
||||||
{
|
|
||||||
return reinterpret_cast <raw_parser*> (
|
|
||||||
p->data)->do_message_complete();
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
auto
|
|
||||||
raw_parser::callback::on_request () ->
|
|
||||||
error_code
|
|
||||||
{
|
|
||||||
return error_code();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto
|
|
||||||
raw_parser::callback::on_response () ->
|
|
||||||
error_code
|
|
||||||
{
|
|
||||||
return error_code();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto
|
|
||||||
raw_parser::callback::on_url(
|
|
||||||
void const*, std::size_t) ->
|
|
||||||
error_code
|
|
||||||
{
|
|
||||||
return error_code();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto
|
|
||||||
raw_parser::callback::on_status (int,
|
|
||||||
void const*, std::size_t) ->
|
|
||||||
error_code
|
|
||||||
{
|
|
||||||
return error_code();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto
|
|
||||||
raw_parser::callback::on_header_field (
|
|
||||||
void const*, std::size_t) ->
|
|
||||||
error_code
|
|
||||||
{
|
|
||||||
return error_code();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto
|
|
||||||
raw_parser::callback::on_header_value (
|
|
||||||
void const*, std::size_t) ->
|
|
||||||
error_code
|
|
||||||
{
|
|
||||||
return error_code();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto
|
|
||||||
raw_parser::callback::on_headers_done (
|
|
||||||
bool) ->
|
|
||||||
error_code
|
|
||||||
{
|
|
||||||
return error_code();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto
|
|
||||||
raw_parser::callback::on_body (
|
|
||||||
bool, void const*, std::size_t) ->
|
|
||||||
error_code
|
|
||||||
{
|
|
||||||
return error_code();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto
|
|
||||||
raw_parser::callback::on_message_complete (
|
|
||||||
bool) ->
|
|
||||||
error_code
|
|
||||||
{
|
|
||||||
return error_code();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -48,6 +48,10 @@ enum class method_t
|
|||||||
http_proppatch,
|
http_proppatch,
|
||||||
http_search,
|
http_search,
|
||||||
http_unlock,
|
http_unlock,
|
||||||
|
http_bind,
|
||||||
|
http_rebind,
|
||||||
|
http_unbind,
|
||||||
|
http_acl,
|
||||||
|
|
||||||
// subversion
|
// subversion
|
||||||
http_report,
|
http_report,
|
||||||
@@ -63,7 +67,14 @@ enum class method_t
|
|||||||
|
|
||||||
// RFC-5789
|
// RFC-5789
|
||||||
http_patch,
|
http_patch,
|
||||||
http_purge
|
http_purge,
|
||||||
|
|
||||||
|
// CalDav
|
||||||
|
http_mkcalendar,
|
||||||
|
|
||||||
|
// RFC-2068, section 19.6.1.2
|
||||||
|
http_link,
|
||||||
|
http_unlink
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
|
|||||||
@@ -1,202 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_HTTP_RAW_PARSER_H_INCLUDED
|
|
||||||
#define BEAST_HTTP_RAW_PARSER_H_INCLUDED
|
|
||||||
|
|
||||||
#include <beast/utility/empty_base_optimization.h>
|
|
||||||
|
|
||||||
#include <boost/system/error_code.hpp> // change to <system_error> soon
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
namespace joyent {
|
|
||||||
struct http_parser;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace http {
|
|
||||||
|
|
||||||
/** Raw HTTP message parser.
|
|
||||||
This is implemented using a zero-allocation state machine. The caller
|
|
||||||
is responsible for all buffer management.
|
|
||||||
*/
|
|
||||||
class raw_parser
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
using error_code = boost::system::error_code;
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum message_type
|
|
||||||
{
|
|
||||||
request,
|
|
||||||
response
|
|
||||||
};
|
|
||||||
|
|
||||||
struct callback
|
|
||||||
{
|
|
||||||
/** Called when the first byte of an HTTP request is received. */
|
|
||||||
virtual
|
|
||||||
error_code
|
|
||||||
on_request ();
|
|
||||||
|
|
||||||
/** Called when the first byte of an HTTP response is received. */
|
|
||||||
virtual
|
|
||||||
error_code
|
|
||||||
on_response ();
|
|
||||||
|
|
||||||
/** Called repeatedly to provide parts of the URL.
|
|
||||||
This is only for requests.
|
|
||||||
*/
|
|
||||||
virtual
|
|
||||||
error_code
|
|
||||||
on_url (
|
|
||||||
void const* in, std::size_t bytes);
|
|
||||||
|
|
||||||
/** Called when the status is received.
|
|
||||||
This is only for responses.
|
|
||||||
*/
|
|
||||||
virtual
|
|
||||||
error_code
|
|
||||||
on_status (int status_code,
|
|
||||||
void const* in, std::size_t bytes);
|
|
||||||
|
|
||||||
/** Called repeatedly to provide parts of a field. */
|
|
||||||
virtual
|
|
||||||
error_code
|
|
||||||
on_header_field (
|
|
||||||
void const* in, std::size_t bytes);
|
|
||||||
|
|
||||||
/** Called repeatedly to provide parts of a value. */
|
|
||||||
virtual
|
|
||||||
error_code
|
|
||||||
on_header_value (
|
|
||||||
void const* in, std::size_t bytes);
|
|
||||||
|
|
||||||
/** Called when there are no more bytes of headers remaining. */
|
|
||||||
virtual
|
|
||||||
error_code
|
|
||||||
on_headers_done (
|
|
||||||
bool keep_alive);
|
|
||||||
|
|
||||||
/** Called repeatedly to provide parts of the body. */
|
|
||||||
virtual
|
|
||||||
error_code
|
|
||||||
on_body (bool is_final,
|
|
||||||
void const* in, std::size_t bytes);
|
|
||||||
|
|
||||||
/** Called when there are no more bytes of body remaining. */
|
|
||||||
virtual
|
|
||||||
error_code on_message_complete (
|
|
||||||
bool keep_alive);
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit raw_parser (callback& cb);
|
|
||||||
|
|
||||||
~raw_parser();
|
|
||||||
|
|
||||||
/** Prepare to parse a new message.
|
|
||||||
The previous state information, if any, is discarded.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
reset (message_type type);
|
|
||||||
|
|
||||||
/** Processs message data.
|
|
||||||
The return value includes the error code if any,
|
|
||||||
and the number of bytes consumed in the input sequence.
|
|
||||||
*/
|
|
||||||
std::pair <error_code, std::size_t>
|
|
||||||
process_data (void const* in, std::size_t bytes);
|
|
||||||
|
|
||||||
/** Notify the parser the end of the data is reached.
|
|
||||||
Normally this will be called in response to the remote
|
|
||||||
end closing down its half of the connection.
|
|
||||||
*/
|
|
||||||
error_code
|
|
||||||
process_eof ();
|
|
||||||
|
|
||||||
private:
|
|
||||||
int do_message_start ();
|
|
||||||
int do_url (char const* in, std::size_t bytes);
|
|
||||||
int do_status (char const* in, std::size_t bytes);
|
|
||||||
int do_header_field (char const* in, std::size_t bytes);
|
|
||||||
int do_header_value (char const* in, std::size_t bytes);
|
|
||||||
int do_headers_done ();
|
|
||||||
int do_body (char const* in, std::size_t bytes);
|
|
||||||
int do_message_complete ();
|
|
||||||
|
|
||||||
static int on_message_start (joyent::http_parser*);
|
|
||||||
static int on_url (joyent::http_parser*, char const*, std::size_t);
|
|
||||||
static int on_status (joyent::http_parser*, char const*, std::size_t);
|
|
||||||
static int on_header_field (joyent::http_parser*, char const*, std::size_t);
|
|
||||||
static int on_header_value (joyent::http_parser*, char const*, std::size_t);
|
|
||||||
static int on_headers_done (joyent::http_parser*);
|
|
||||||
static int on_body (joyent::http_parser*, char const*, std::size_t);
|
|
||||||
static int on_message_complete (joyent::http_parser*);
|
|
||||||
|
|
||||||
// These structures must exactly match the
|
|
||||||
// declarations in joyent http_parser.h include
|
|
||||||
//
|
|
||||||
struct state_t
|
|
||||||
{
|
|
||||||
unsigned int type : 2;
|
|
||||||
unsigned int flags : 6;
|
|
||||||
unsigned int state : 8;
|
|
||||||
unsigned int header_state : 8;
|
|
||||||
unsigned int index : 8;
|
|
||||||
std::uint32_t nread;
|
|
||||||
std::uint64_t content_length;
|
|
||||||
unsigned short http_major;
|
|
||||||
unsigned short http_minor;
|
|
||||||
unsigned int status_code : 16;
|
|
||||||
unsigned int method : 8;
|
|
||||||
unsigned int http_errno : 7;
|
|
||||||
unsigned int upgrade : 1;
|
|
||||||
void *data;
|
|
||||||
};
|
|
||||||
|
|
||||||
using data_cb_t = int (*) (
|
|
||||||
state_t*, const char *at, size_t length);
|
|
||||||
using cb_t = int (*) (state_t*);
|
|
||||||
|
|
||||||
struct hooks_t
|
|
||||||
{
|
|
||||||
cb_t on_message_begin;
|
|
||||||
data_cb_t on_url;
|
|
||||||
data_cb_t on_status;
|
|
||||||
data_cb_t on_header_field;
|
|
||||||
data_cb_t on_header_value;
|
|
||||||
cb_t on_headers_complete;
|
|
||||||
data_cb_t on_body;
|
|
||||||
cb_t on_message_complete;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::reference_wrapper <callback> m_cb;
|
|
||||||
error_code m_ec;
|
|
||||||
char m_state [sizeof(state_t)];
|
|
||||||
char m_hooks [sizeof(hooks_t)];
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -65,6 +65,7 @@ public:
|
|||||||
void
|
void
|
||||||
notify (std::chrono::duration <Rep, Period> const& value) const
|
notify (std::chrono::duration <Rep, Period> const& value) const
|
||||||
{
|
{
|
||||||
|
using namespace std::chrono;
|
||||||
if (m_impl)
|
if (m_impl)
|
||||||
m_impl->notify (ceil <value_type> (value));
|
m_impl->notify (ceil <value_type> (value));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -218,7 +218,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VFALCO TODO IPv6 support
|
// VFALCO TODO IPv6 support
|
||||||
bassertfalse;
|
assert(false);
|
||||||
return boost::asio::ip::udp::endpoint (
|
return boost::asio::ip::udp::endpoint (
|
||||||
boost::asio::ip::address_v6 (), 0);
|
boost::asio::ip::address_v6 (), 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,11 @@ struct is_call_possible_udt2
|
|||||||
int operator()(int) const;
|
int operator()(int) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct is_call_possible_udt3
|
||||||
|
{
|
||||||
|
int operator()(int);
|
||||||
|
};
|
||||||
|
|
||||||
static_assert(is_call_possible<
|
static_assert(is_call_possible<
|
||||||
is_call_possible_udt1, void(int)>::value, "");
|
is_call_possible_udt1, void(int)>::value, "");
|
||||||
|
|
||||||
@@ -86,6 +91,11 @@ static_assert(! is_call_possible<
|
|||||||
static_assert(! is_call_possible<
|
static_assert(! is_call_possible<
|
||||||
is_call_possible_udt2, void(void)>::value, "");
|
is_call_possible_udt2, void(void)>::value, "");
|
||||||
|
|
||||||
|
static_assert(is_call_possible<
|
||||||
|
is_call_possible_udt3, int(int)>::value, "");
|
||||||
|
|
||||||
|
static_assert(! is_call_possible<
|
||||||
|
is_call_possible_udt3 const, int(int)>::value, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_MODULE_ASIO_BOOSTINCLUDES_H_INCLUDED
|
|
||||||
#define BEAST_MODULE_ASIO_BOOSTINCLUDES_H_INCLUDED
|
|
||||||
|
|
||||||
// Make sure we take care of fixing boost::bind oddities first.
|
|
||||||
#if !defined(BEAST_CORE_H_INCLUDED)
|
|
||||||
#error core.h must be included before including this file
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// These should have already been set in your project, but
|
|
||||||
// if you forgot then we will be optimistic and choose the latest.
|
|
||||||
//
|
|
||||||
#if BEAST_WIN32
|
|
||||||
# ifndef _WIN32_WINNT
|
|
||||||
# pragma message ("Warning: _WIN32_WINNT was not set in your project")
|
|
||||||
# define _WIN32_WINNT 0x0600
|
|
||||||
# endif
|
|
||||||
# ifndef _VARIADIC_MAX
|
|
||||||
# define _VARIADIC_MAX 10
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// work-around for broken <boost/get_pointer.hpp>
|
|
||||||
#include <beast/boost/get_pointer.h>
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#include <beast/module/asio/HTTPField.h>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
HTTPField::HTTPField ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HTTPField::HTTPField (String name_, String value_)
|
|
||||||
: m_name (name_)
|
|
||||||
, m_value (value_)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HTTPField::HTTPField (HTTPField const& other)
|
|
||||||
: m_name (other.m_name)
|
|
||||||
, m_value (other.m_value)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HTTPField& HTTPField::operator= (HTTPField const& other)
|
|
||||||
{
|
|
||||||
m_name = other.m_name;
|
|
||||||
m_value = other.m_value;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
String HTTPField::name () const
|
|
||||||
{
|
|
||||||
return m_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
String HTTPField::value () const
|
|
||||||
{
|
|
||||||
return m_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_MODULE_ASIO_HTTPFIELD_H_INCLUDED
|
|
||||||
#define BEAST_MODULE_ASIO_HTTPFIELD_H_INCLUDED
|
|
||||||
|
|
||||||
#include <beast/strings/String.h>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
/** A single header.
|
|
||||||
The header is a field/value pair.
|
|
||||||
Time complexity of copies is constant.
|
|
||||||
*/
|
|
||||||
class HTTPField
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HTTPField ();
|
|
||||||
HTTPField (String name_, String value_);
|
|
||||||
HTTPField (HTTPField const& other);
|
|
||||||
HTTPField& operator= (HTTPField const& other);
|
|
||||||
String name () const;
|
|
||||||
String value () const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
String m_name;
|
|
||||||
String m_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#include <beast/module/asio/HTTPHeaders.h>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
HTTPHeaders::HTTPHeaders ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HTTPHeaders::HTTPHeaders (StringPairArray& fields)
|
|
||||||
{
|
|
||||||
m_fields.swapWith (fields);
|
|
||||||
}
|
|
||||||
|
|
||||||
HTTPHeaders::HTTPHeaders (StringPairArray const& fields)
|
|
||||||
: m_fields (fields)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HTTPHeaders::HTTPHeaders (HTTPHeaders const& other)
|
|
||||||
: m_fields (other.m_fields)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HTTPHeaders& HTTPHeaders::operator= (HTTPHeaders const& other)
|
|
||||||
{
|
|
||||||
m_fields = other.m_fields;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HTTPHeaders::empty () const
|
|
||||||
{
|
|
||||||
return m_fields.size () == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t HTTPHeaders::size () const
|
|
||||||
{
|
|
||||||
return m_fields.size ();
|
|
||||||
}
|
|
||||||
|
|
||||||
HTTPField HTTPHeaders::at (int index) const
|
|
||||||
{
|
|
||||||
return HTTPField (m_fields.getAllKeys () [index],
|
|
||||||
m_fields.getAllValues () [index]);
|
|
||||||
}
|
|
||||||
|
|
||||||
HTTPField HTTPHeaders::operator[] (int index) const
|
|
||||||
{
|
|
||||||
return at (index);
|
|
||||||
}
|
|
||||||
|
|
||||||
String HTTPHeaders::get (String const& field) const
|
|
||||||
{
|
|
||||||
return m_fields [field];
|
|
||||||
}
|
|
||||||
|
|
||||||
String HTTPHeaders::operator[] (String const& field) const
|
|
||||||
{
|
|
||||||
return get (field);
|
|
||||||
}
|
|
||||||
|
|
||||||
String HTTPHeaders::toString () const
|
|
||||||
{
|
|
||||||
String s;
|
|
||||||
for (int i = 0; i < m_fields.size (); ++i)
|
|
||||||
{
|
|
||||||
HTTPField const field (at(i));
|
|
||||||
s << field.name() << ": " << field.value() << newLine;
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::map <std::string, std::string>
|
|
||||||
HTTPHeaders::build_map() const
|
|
||||||
{
|
|
||||||
std::map <std::string, std::string> c;
|
|
||||||
auto const& k (m_fields.getAllKeys());
|
|
||||||
auto const& v (m_fields.getAllValues());
|
|
||||||
for (std::size_t i = 0; i < m_fields.size(); ++i)
|
|
||||||
{
|
|
||||||
auto key (k[i].toStdString());
|
|
||||||
auto const value (v[i].toStdString());
|
|
||||||
std::transform (key.begin(), key.end(), key.begin(), ::tolower);
|
|
||||||
c[key] = value;
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_MODULE_ASIO_HTTPHEADERS_H_INCLUDED
|
|
||||||
#define BEAST_MODULE_ASIO_HTTPHEADERS_H_INCLUDED
|
|
||||||
|
|
||||||
#include <beast/module/asio/HTTPField.h>
|
|
||||||
#include <beast/module/core/text/StringPairArray.h>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
/** A set of HTTP headers. */
|
|
||||||
class HTTPHeaders
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/** Construct an empty set of headers. */
|
|
||||||
HTTPHeaders ();
|
|
||||||
|
|
||||||
/** Construct headers taking ownership of a field array.
|
|
||||||
The callers value is overwritten.
|
|
||||||
*/
|
|
||||||
HTTPHeaders (StringPairArray& fields);
|
|
||||||
|
|
||||||
/** Construct a copy of headers from an array.*/
|
|
||||||
HTTPHeaders (StringPairArray const& fields);
|
|
||||||
|
|
||||||
/** Construct a copy of headers. */
|
|
||||||
HTTPHeaders (HTTPHeaders const& other);
|
|
||||||
|
|
||||||
/** Assign a copy of headers. */
|
|
||||||
HTTPHeaders& operator= (HTTPHeaders const& other);
|
|
||||||
|
|
||||||
/** Returns `true` if the container is empty. */
|
|
||||||
bool empty () const;
|
|
||||||
|
|
||||||
/** Returns the number of fields in the container. */
|
|
||||||
std::size_t size () const;
|
|
||||||
|
|
||||||
/** Random access to fields by index. */
|
|
||||||
/** @{ */
|
|
||||||
HTTPField at (int index) const;
|
|
||||||
HTTPField operator[] (int index) const;
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
/** Associative access to fields by name.
|
|
||||||
If the field is not present, an empty string is returned.
|
|
||||||
*/
|
|
||||||
/** @{ */
|
|
||||||
String get (String const& field) const;
|
|
||||||
String operator[] (String const& field) const;
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
/** Outputs all the headers into one string. */
|
|
||||||
String toString () const;
|
|
||||||
|
|
||||||
// VFALCO HACK to present the headers in a useful format
|
|
||||||
std::map <std::string, std::string>
|
|
||||||
build_map() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
StringPairArray m_fields;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#include <beast/module/asio/HTTPMessage.h>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
HTTPMessage::HTTPMessage (HTTPVersion const& version_,
|
|
||||||
StringPairArray& fields,
|
|
||||||
DynamicBuffer& body)
|
|
||||||
: m_version (version_)
|
|
||||||
, m_headers (fields)
|
|
||||||
{
|
|
||||||
m_body.swapWith (body);
|
|
||||||
}
|
|
||||||
|
|
||||||
HTTPVersion const& HTTPMessage::version () const
|
|
||||||
{
|
|
||||||
return m_version;
|
|
||||||
}
|
|
||||||
|
|
||||||
HTTPHeaders const& HTTPMessage::headers () const
|
|
||||||
{
|
|
||||||
return m_headers;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicBuffer const& HTTPMessage::body () const
|
|
||||||
{
|
|
||||||
return m_body;
|
|
||||||
}
|
|
||||||
|
|
||||||
String HTTPMessage::toString () const
|
|
||||||
{
|
|
||||||
String s;
|
|
||||||
s << "HTTP " << version().toString() << newLine;
|
|
||||||
s << m_headers.toString ();
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_MODULE_ASIO_HTTPMESSAGE_H_INCLUDED
|
|
||||||
#define BEAST_MODULE_ASIO_HTTPMESSAGE_H_INCLUDED
|
|
||||||
|
|
||||||
#include <beast/module/asio/HTTPHeaders.h>
|
|
||||||
#include <beast/module/asio/HTTPVersion.h>
|
|
||||||
|
|
||||||
#include <beast/smart_ptr/SharedObject.h>
|
|
||||||
#include <beast/net/DynamicBuffer.h>
|
|
||||||
#include <beast/module/core/text/StringPairArray.h>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
/** A complete HTTP message.
|
|
||||||
|
|
||||||
This provides the information common to all HTTP messages, including
|
|
||||||
the version, content body, and headers.
|
|
||||||
Derived classes provide the request or response specific data.
|
|
||||||
|
|
||||||
Because a single HTTP message can be a fairly expensive object to
|
|
||||||
make copies of, this is a SharedObject.
|
|
||||||
|
|
||||||
@see HTTPRequest, HTTPResponse
|
|
||||||
*/
|
|
||||||
class HTTPMessage : public SharedObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/** Construct the common HTTP message parts from values.
|
|
||||||
Ownership of the fields and body parameters are
|
|
||||||
transferred from the caller.
|
|
||||||
*/
|
|
||||||
HTTPMessage (HTTPVersion const& version_,
|
|
||||||
StringPairArray& fields,
|
|
||||||
DynamicBuffer& body);
|
|
||||||
|
|
||||||
/** Returns the HTTP version of this message. */
|
|
||||||
HTTPVersion const& version () const;
|
|
||||||
|
|
||||||
/** Returns the set of HTTP headers associated with this message. */
|
|
||||||
HTTPHeaders const& headers () const;
|
|
||||||
|
|
||||||
/** Returns the content-body. */
|
|
||||||
DynamicBuffer const& body () const;
|
|
||||||
|
|
||||||
/** Outputs all the HTTPMessage data excluding the body into a string. */
|
|
||||||
String toString () const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
HTTPVersion m_version;
|
|
||||||
HTTPHeaders m_headers;
|
|
||||||
DynamicBuffer m_body;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#include <beast/module/asio/HTTPParser.h>
|
|
||||||
#include <beast/module/asio/HTTPParserImpl.h>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
HTTPParser::HTTPParser (Type type)
|
|
||||||
: m_type (type)
|
|
||||||
, m_impl (new HTTPParserImpl (
|
|
||||||
(type == typeResponse) ? joyent::HTTP_RESPONSE : joyent::HTTP_REQUEST))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HTTPParser::~HTTPParser ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char HTTPParser::error () const
|
|
||||||
{
|
|
||||||
return m_impl->http_errno ();
|
|
||||||
}
|
|
||||||
|
|
||||||
String HTTPParser::message () const
|
|
||||||
{
|
|
||||||
return m_impl->http_errno_message ();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t HTTPParser::process (void const* buf, std::size_t bytes)
|
|
||||||
{
|
|
||||||
std::size_t const bytes_used (m_impl->process (buf, bytes));
|
|
||||||
|
|
||||||
if (m_impl->finished ())
|
|
||||||
{
|
|
||||||
if (m_type == typeRequest)
|
|
||||||
{
|
|
||||||
m_request = new HTTPRequest (
|
|
||||||
m_impl->version (),
|
|
||||||
m_impl->fields (),
|
|
||||||
m_impl->body (),
|
|
||||||
m_impl->method ());
|
|
||||||
}
|
|
||||||
else if (m_type == typeResponse)
|
|
||||||
{
|
|
||||||
m_response = new HTTPResponse (
|
|
||||||
m_impl->version (),
|
|
||||||
m_impl->fields (),
|
|
||||||
m_impl->body (),
|
|
||||||
m_impl->status_code ());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bassertfalse;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytes_used;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HTTPParser::process_eof ()
|
|
||||||
{
|
|
||||||
m_impl->process_eof ();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HTTPParser::finished () const
|
|
||||||
{
|
|
||||||
return m_impl->finished();
|
|
||||||
}
|
|
||||||
|
|
||||||
StringPairArray const& HTTPParser::fields () const
|
|
||||||
{
|
|
||||||
return m_impl->fields();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HTTPParser::headersComplete () const
|
|
||||||
{
|
|
||||||
return m_impl->headers_complete();
|
|
||||||
}
|
|
||||||
|
|
||||||
SharedPtr <HTTPRequest> const& HTTPParser::request ()
|
|
||||||
{
|
|
||||||
bassert (m_type == typeRequest);
|
|
||||||
|
|
||||||
return m_request;
|
|
||||||
}
|
|
||||||
|
|
||||||
SharedPtr <HTTPResponse> const& HTTPParser::response ()
|
|
||||||
{
|
|
||||||
bassert (m_type == typeResponse);
|
|
||||||
|
|
||||||
return m_response;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_MODULE_ASIO_HTTPPARSER_H_INCLUDED
|
|
||||||
#define BEAST_MODULE_ASIO_HTTPPARSER_H_INCLUDED
|
|
||||||
|
|
||||||
#include <beast/module/asio/HTTPRequest.h>
|
|
||||||
#include <beast/module/asio/HTTPResponse.h>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
class HTTPParserImpl;
|
|
||||||
|
|
||||||
/** A parser for HTTPRequest and HTTPResponse objects. */
|
|
||||||
class HTTPParser
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum Type
|
|
||||||
{
|
|
||||||
typeRequest,
|
|
||||||
typeResponse
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Construct a new parser for the specified HTTPMessage type. */
|
|
||||||
explicit HTTPParser (Type type);
|
|
||||||
|
|
||||||
/** Destroy the parser. */
|
|
||||||
~HTTPParser ();
|
|
||||||
|
|
||||||
/** Returns a non zero error code if parsing fails. */
|
|
||||||
unsigned char error () const;
|
|
||||||
|
|
||||||
/** Returns the error message text when error is non zero. */
|
|
||||||
String message () const;
|
|
||||||
|
|
||||||
/** Parse the buffer and return the amount used.
|
|
||||||
Typically it is an error when this returns less than
|
|
||||||
the amount passed in.
|
|
||||||
*/
|
|
||||||
std::size_t process (void const* buf, std::size_t bytes);
|
|
||||||
|
|
||||||
/** Notify the parser that eof was received.
|
|
||||||
*/
|
|
||||||
void process_eof ();
|
|
||||||
|
|
||||||
/** Returns `true` when parsing is successful and complete. */
|
|
||||||
bool finished () const;
|
|
||||||
|
|
||||||
/** Peek at the header fields as they are being built.
|
|
||||||
Only complete pairs will show up, never partial strings.
|
|
||||||
*/
|
|
||||||
StringPairArray const& fields () const;
|
|
||||||
|
|
||||||
/** Returns `true` if all the HTTP headers have been received. */
|
|
||||||
bool headersComplete () const;
|
|
||||||
|
|
||||||
/** Return the HTTPRequest object produced from the parsiing.
|
|
||||||
Only valid after finished returns `true`.
|
|
||||||
*/
|
|
||||||
SharedPtr <HTTPRequest> const& request ();
|
|
||||||
|
|
||||||
/** Return the HTTPResponse object produced from the parsing.
|
|
||||||
Only valid after finished returns `true`.
|
|
||||||
*/
|
|
||||||
SharedPtr <HTTPResponse> const& response ();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Type m_type;
|
|
||||||
std::unique_ptr <HTTPParserImpl> m_impl;
|
|
||||||
SharedPtr <HTTPRequest> m_request;
|
|
||||||
SharedPtr <HTTPResponse> m_response;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,276 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_MODULE_ASIO_HTTPPARSERIMPL_H_INCLUDED
|
|
||||||
#define BEAST_MODULE_ASIO_HTTPPARSERIMPL_H_INCLUDED
|
|
||||||
|
|
||||||
#include <beast/http/impl/joyent_parser.h>
|
|
||||||
#include <boost/asio/buffer.hpp>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
class HTTPParserImpl
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
stringReservation = 256
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit HTTPParserImpl (enum joyent::http_parser_type type)
|
|
||||||
: m_finished (false)
|
|
||||||
, m_was_value (false)
|
|
||||||
, m_headersComplete (false)
|
|
||||||
{
|
|
||||||
m_settings.on_message_begin = &HTTPParserImpl::on_message_begin;
|
|
||||||
m_settings.on_url = &HTTPParserImpl::on_url;
|
|
||||||
m_settings.on_status = &HTTPParserImpl::on_status;
|
|
||||||
m_settings.on_header_field = &HTTPParserImpl::on_header_field;
|
|
||||||
m_settings.on_header_value = &HTTPParserImpl::on_header_value;
|
|
||||||
m_settings.on_headers_complete = &HTTPParserImpl::on_headers_complete;
|
|
||||||
m_settings.on_body = &HTTPParserImpl::on_body;
|
|
||||||
m_settings.on_message_complete = &HTTPParserImpl::on_message_complete;
|
|
||||||
|
|
||||||
m_field.reserve (stringReservation);
|
|
||||||
m_value.reserve (stringReservation);
|
|
||||||
|
|
||||||
joyent::http_parser_init (&m_parser, type);
|
|
||||||
m_parser.data = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
~HTTPParserImpl ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char error () const
|
|
||||||
{
|
|
||||||
return m_parser.http_errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
String message () const
|
|
||||||
{
|
|
||||||
return String (joyent::http_errno_name (static_cast <
|
|
||||||
enum joyent::http_errno> (m_parser.http_errno)));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t process (void const* buf, std::size_t bytes)
|
|
||||||
{
|
|
||||||
return joyent::http_parser_execute (&m_parser,
|
|
||||||
&m_settings, static_cast <char const*> (buf), bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
void process_eof ()
|
|
||||||
{
|
|
||||||
joyent::http_parser_execute (&m_parser, &m_settings, nullptr, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool finished () const
|
|
||||||
{
|
|
||||||
return m_finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
HTTPVersion version () const
|
|
||||||
{
|
|
||||||
return HTTPVersion (
|
|
||||||
m_parser.http_major, m_parser.http_minor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only for HTTPResponse!
|
|
||||||
unsigned short status_code () const
|
|
||||||
{
|
|
||||||
return m_parser.status_code;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only for HTTPRequest!
|
|
||||||
unsigned char method () const
|
|
||||||
{
|
|
||||||
return m_parser.method;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char http_errno () const
|
|
||||||
{
|
|
||||||
return m_parser.http_errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
String http_errno_message () const
|
|
||||||
{
|
|
||||||
return String (joyent::http_errno_name (
|
|
||||||
static_cast <enum joyent::http_errno> (
|
|
||||||
m_parser.http_errno)));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool upgrade () const
|
|
||||||
{
|
|
||||||
return m_parser.upgrade != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringPairArray& fields ()
|
|
||||||
{
|
|
||||||
return m_fields;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool headers_complete () const
|
|
||||||
{
|
|
||||||
return m_headersComplete;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicBuffer& body ()
|
|
||||||
{
|
|
||||||
return m_body;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void addFieldValue ()
|
|
||||||
{
|
|
||||||
if (m_field.size () > 0 && m_value.size () > 0)
|
|
||||||
m_fields.set (m_field, m_value);
|
|
||||||
m_field.resize (0);
|
|
||||||
m_value.resize (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int onMessageBegin ()
|
|
||||||
{
|
|
||||||
int ec (0);
|
|
||||||
return ec;
|
|
||||||
}
|
|
||||||
|
|
||||||
int onUrl (char const*, std::size_t)
|
|
||||||
{
|
|
||||||
int ec (0);
|
|
||||||
// This is for HTTP Request
|
|
||||||
return ec;
|
|
||||||
}
|
|
||||||
|
|
||||||
int onStatus ()
|
|
||||||
{
|
|
||||||
int ec (0);
|
|
||||||
return ec;
|
|
||||||
}
|
|
||||||
|
|
||||||
int onHeaderField (char const* at, std::size_t length)
|
|
||||||
{
|
|
||||||
int ec (0);
|
|
||||||
if (m_was_value)
|
|
||||||
{
|
|
||||||
addFieldValue ();
|
|
||||||
m_was_value = false;
|
|
||||||
}
|
|
||||||
m_field.append (at, length);
|
|
||||||
return ec;
|
|
||||||
}
|
|
||||||
|
|
||||||
int onHeaderValue (char const* at, std::size_t length)
|
|
||||||
{
|
|
||||||
int ec (0);
|
|
||||||
m_value.append (at, length);
|
|
||||||
m_was_value = true;
|
|
||||||
return ec;
|
|
||||||
}
|
|
||||||
|
|
||||||
int onHeadersComplete ()
|
|
||||||
{
|
|
||||||
m_headersComplete = true;
|
|
||||||
int ec (0);
|
|
||||||
addFieldValue ();
|
|
||||||
return ec;
|
|
||||||
}
|
|
||||||
|
|
||||||
int onBody (char const* at, std::size_t length)
|
|
||||||
{
|
|
||||||
m_body.commit (boost::asio::buffer_copy (
|
|
||||||
m_body.prepare <boost::asio::mutable_buffer> (length),
|
|
||||||
boost::asio::buffer (at, length)));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int onMessageComplete ()
|
|
||||||
{
|
|
||||||
int ec (0);
|
|
||||||
m_finished = true;
|
|
||||||
return ec;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static int on_message_begin (joyent::http_parser* parser)
|
|
||||||
{
|
|
||||||
return static_cast <HTTPParserImpl*> (parser->data)->
|
|
||||||
onMessageBegin ();
|
|
||||||
}
|
|
||||||
|
|
||||||
static int on_url (joyent::http_parser* parser, const char *at, size_t length)
|
|
||||||
{
|
|
||||||
return static_cast <HTTPParserImpl*> (parser->data)->
|
|
||||||
onUrl (at, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int on_status (joyent::http_parser* parser,
|
|
||||||
char const* /*at*/, size_t /*length*/)
|
|
||||||
{
|
|
||||||
return static_cast <HTTPParserImpl*> (parser->data)->
|
|
||||||
onStatus ();
|
|
||||||
}
|
|
||||||
|
|
||||||
static int on_header_field (joyent::http_parser* parser,
|
|
||||||
const char *at, size_t length)
|
|
||||||
{
|
|
||||||
return static_cast <HTTPParserImpl*> (parser->data)->
|
|
||||||
onHeaderField (at, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int on_header_value (joyent::http_parser* parser,
|
|
||||||
const char *at, size_t length)
|
|
||||||
{
|
|
||||||
return static_cast <HTTPParserImpl*> (parser->data)->
|
|
||||||
onHeaderValue (at, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int on_headers_complete (joyent::http_parser* parser)
|
|
||||||
{
|
|
||||||
return static_cast <HTTPParserImpl*> (parser->data)->
|
|
||||||
onHeadersComplete ();
|
|
||||||
}
|
|
||||||
|
|
||||||
static int on_body (joyent::http_parser* parser,
|
|
||||||
const char *at, size_t length)
|
|
||||||
{
|
|
||||||
return static_cast <HTTPParserImpl*> (parser->data)->
|
|
||||||
onBody (at, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int on_message_complete (joyent::http_parser* parser)
|
|
||||||
{
|
|
||||||
return static_cast <HTTPParserImpl*> (parser->data)->
|
|
||||||
onMessageComplete ();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool m_finished;
|
|
||||||
joyent::http_parser_settings m_settings;
|
|
||||||
joyent::http_parser m_parser;
|
|
||||||
StringPairArray m_fields;
|
|
||||||
bool m_was_value;
|
|
||||||
std::string m_field;
|
|
||||||
std::string m_value;
|
|
||||||
bool m_headersComplete;
|
|
||||||
DynamicBuffer m_body;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#include <beast/module/asio/HTTPRequest.h>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
HTTPRequest::HTTPRequest (
|
|
||||||
HTTPVersion const& version_,
|
|
||||||
StringPairArray& fields,
|
|
||||||
DynamicBuffer& body,
|
|
||||||
unsigned short method_)
|
|
||||||
: HTTPMessage (version_, fields, body)
|
|
||||||
, m_method (method_)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned short HTTPRequest::method () const
|
|
||||||
{
|
|
||||||
return m_method;
|
|
||||||
}
|
|
||||||
|
|
||||||
String HTTPRequest::toString () const
|
|
||||||
{
|
|
||||||
String s;
|
|
||||||
s << "Method: " << String::fromNumber (method ()) << newLine;
|
|
||||||
s << this->HTTPMessage::toString ();
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_MODULE_ASIO_HTTPREQUEST_H_INCLUDED
|
|
||||||
#define BEAST_MODULE_ASIO_HTTPREQUEST_H_INCLUDED
|
|
||||||
|
|
||||||
#include <beast/module/asio/HTTPMessage.h>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
class HTTPRequest : public HTTPMessage
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/** Construct a complete response from values.
|
|
||||||
Ownership of the fields and body parameters are
|
|
||||||
transferred from the caller.
|
|
||||||
*/
|
|
||||||
HTTPRequest (
|
|
||||||
HTTPVersion const& version_,
|
|
||||||
StringPairArray& fields,
|
|
||||||
DynamicBuffer& body,
|
|
||||||
unsigned short method_);
|
|
||||||
|
|
||||||
unsigned short method () const;
|
|
||||||
|
|
||||||
/** Convert the request into a string, excluding the body. */
|
|
||||||
String toString () const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
unsigned short m_method;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#include <beast/module/asio/HTTPRequestParser.h>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
HTTPRequestParser::HTTPRequestParser ()
|
|
||||||
: HTTPParser (typeRequest)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HTTPRequestParser::~HTTPRequestParser ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
SharedPtr <HTTPRequest> const& HTTPRequestParser::request ()
|
|
||||||
{
|
|
||||||
return m_request;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_MODULE_ASIO_HTTPREQUESTPARSER_H_INCLUDED
|
|
||||||
#define BEAST_MODULE_ASIO_HTTPREQUESTPARSER_H_INCLUDED
|
|
||||||
|
|
||||||
#include <beast/module/asio/HTTPParser.h>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
/** A parser for HTTPRequest objects. */
|
|
||||||
class HTTPRequestParser : public HTTPParser
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/** Construct a new parser for the specified HTTPMessage type. */
|
|
||||||
HTTPRequestParser ();
|
|
||||||
|
|
||||||
/** Destroy the parser. */
|
|
||||||
~HTTPRequestParser ();
|
|
||||||
|
|
||||||
/** Return the HTTPRequest object produced from the parsing. */
|
|
||||||
SharedPtr <HTTPRequest> const& request ();
|
|
||||||
|
|
||||||
private:
|
|
||||||
//SharedPtr <HTTPRequest> m_request;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#include <beast/module/asio/HTTPResponse.h>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
HTTPResponse::HTTPResponse (
|
|
||||||
HTTPVersion const& version_,
|
|
||||||
StringPairArray& fields,
|
|
||||||
DynamicBuffer& body,
|
|
||||||
unsigned short status_)
|
|
||||||
: HTTPMessage (version_, fields, body)
|
|
||||||
, m_status (status_)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned short HTTPResponse::status () const
|
|
||||||
{
|
|
||||||
return m_status;
|
|
||||||
}
|
|
||||||
|
|
||||||
String HTTPResponse::toString () const
|
|
||||||
{
|
|
||||||
String s;
|
|
||||||
s << "Status: " << String::fromNumber (status ()) << newLine;
|
|
||||||
s << this->HTTPMessage::toString ();
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_MODULE_ASIO_HTTPRESPONSE_H_INCLUDED
|
|
||||||
#define BEAST_MODULE_ASIO_HTTPRESPONSE_H_INCLUDED
|
|
||||||
|
|
||||||
#include <beast/module/asio/HTTPMessage.h>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
class HTTPResponse : public HTTPMessage
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/** Construct a complete response from values.
|
|
||||||
Ownership of the fields and body parameters are
|
|
||||||
transferred from the caller.
|
|
||||||
*/
|
|
||||||
HTTPResponse (
|
|
||||||
HTTPVersion const& version_,
|
|
||||||
StringPairArray& fields,
|
|
||||||
DynamicBuffer& body,
|
|
||||||
unsigned short status_);
|
|
||||||
|
|
||||||
unsigned short status () const;
|
|
||||||
|
|
||||||
/** Convert the response into a string, excluding the body. */
|
|
||||||
String toString () const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
unsigned short m_status;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#include <beast/module/asio/HTTPResponseParser.h>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
HTTPResponseParser::HTTPResponseParser ()
|
|
||||||
: HTTPParser (typeResponse)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HTTPResponseParser::~HTTPResponseParser ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
SharedPtr <HTTPResponse> const& HTTPResponseParser::response ()
|
|
||||||
{
|
|
||||||
return m_response;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_MODULE_ASIO_HTTPRESPONSEPARSER_H_INCLUDED
|
|
||||||
#define BEAST_MODULE_ASIO_HTTPRESPONSEPARSER_H_INCLUDED
|
|
||||||
|
|
||||||
#include <beast/module/asio/HTTPParser.h>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
/** A parser for HTTPResponse objects. */
|
|
||||||
class HTTPResponseParser : public HTTPParser
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/** Construct a new parser for the specified HTTPMessage type. */
|
|
||||||
HTTPResponseParser ();
|
|
||||||
|
|
||||||
/** Destroy the parser. */
|
|
||||||
~HTTPResponseParser ();
|
|
||||||
|
|
||||||
/** Return the HTTPResponse object produced from the parsing. */
|
|
||||||
SharedPtr <HTTPResponse> const& response ();
|
|
||||||
|
|
||||||
private:
|
|
||||||
//SharedPtr <HTTPResponse> m_response;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
HTTPVersion::HTTPVersion ()
|
|
||||||
: m_major (0)
|
|
||||||
, m_minor (0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HTTPVersion::HTTPVersion (unsigned short major_, unsigned short minor_)
|
|
||||||
: m_major (major_)
|
|
||||||
, m_minor (minor_)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HTTPVersion::HTTPVersion (HTTPVersion const& other)
|
|
||||||
: m_major (other.m_major)
|
|
||||||
, m_minor (other.m_minor)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HTTPVersion& HTTPVersion::operator= (HTTPVersion const& other)
|
|
||||||
{
|
|
||||||
m_major = other.m_major;
|
|
||||||
m_minor = other.m_minor;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
String HTTPVersion::toString () const
|
|
||||||
{
|
|
||||||
return String::fromNumber (vmajor ()) + "." +
|
|
||||||
String::fromNumber (vminor ());
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned short HTTPVersion::vmajor () const
|
|
||||||
{
|
|
||||||
return m_major;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned short HTTPVersion::vminor () const
|
|
||||||
{
|
|
||||||
return m_minor;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HTTPVersion::operator== (HTTPVersion const& rhs) const
|
|
||||||
{
|
|
||||||
return (m_major == rhs.m_major) && (m_minor == rhs.m_minor);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HTTPVersion::operator!= (HTTPVersion const& rhs) const
|
|
||||||
{
|
|
||||||
return (m_major != rhs.m_major) || (m_minor != rhs.m_minor);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HTTPVersion::operator> (HTTPVersion const& rhs) const
|
|
||||||
{
|
|
||||||
return (m_major > rhs.m_major) ||
|
|
||||||
((m_major == rhs.m_major) && (m_minor > rhs.m_minor));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HTTPVersion::operator>= (HTTPVersion const& rhs) const
|
|
||||||
{
|
|
||||||
return (m_major > rhs.m_major) ||
|
|
||||||
((m_major == rhs.m_major) && (m_minor >= rhs.m_minor));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HTTPVersion::operator< (HTTPVersion const& rhs) const
|
|
||||||
{
|
|
||||||
return (m_major < rhs.m_major) ||
|
|
||||||
((m_major == rhs.m_major) && (m_minor < rhs.m_minor));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HTTPVersion::operator<= (HTTPVersion const& rhs) const
|
|
||||||
{
|
|
||||||
return (m_major < rhs.m_major) ||
|
|
||||||
((m_major == rhs.m_major) && (m_minor <= rhs.m_minor));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_MODULE_ASIO_HTTPVERSION_H_INCLUDED
|
|
||||||
#define BEAST_MODULE_ASIO_HTTPVERSION_H_INCLUDED
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
/** The HTTP version. This is the major.minor version number. */
|
|
||||||
class HTTPVersion
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HTTPVersion ();
|
|
||||||
HTTPVersion (unsigned short major_, unsigned short minor_);
|
|
||||||
HTTPVersion (HTTPVersion const& other);
|
|
||||||
HTTPVersion& operator= (HTTPVersion const& other);
|
|
||||||
String toString () const;
|
|
||||||
unsigned short vmajor () const;
|
|
||||||
unsigned short vminor () const;
|
|
||||||
bool operator== (HTTPVersion const& rhs) const;
|
|
||||||
bool operator!= (HTTPVersion const& rhs) const;
|
|
||||||
bool operator> (HTTPVersion const& rhs) const;
|
|
||||||
bool operator>= (HTTPVersion const& rhs) const;
|
|
||||||
bool operator< (HTTPVersion const& rhs) const;
|
|
||||||
bool operator<= (HTTPVersion const& rhs) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
unsigned short m_major;
|
|
||||||
unsigned short m_minor;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_MODULE_ASIO_OPENSSLINCLUDES_H_INCLUDED
|
|
||||||
#define BEAST_MODULE_ASIO_OPENSSLINCLUDES_H_INCLUDED
|
|
||||||
|
|
||||||
#define OPENSSL_THREAD_DEFINES
|
|
||||||
#include <openssl/opensslconf.h>
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Configure our settings based on what we find
|
|
||||||
//
|
|
||||||
#if defined(OPENSSL_THREADS)
|
|
||||||
# ifndef BEAST_OPENSSL_MULTITHREADED
|
|
||||||
# define BEAST_OPENSSL_MULTITHREADED 1
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
# ifndef BEAST_OPENSSL_MULTITHREADED
|
|
||||||
# define BEAST_OPENSSL_MULTITHREADED 0
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#if BEAST_INCLUDE_BEASTCONFIG
|
|
||||||
#include <BeastConfig.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <beast/module/asio/HTTPField.cpp>
|
|
||||||
#include <beast/module/asio/HTTPHeaders.cpp>
|
|
||||||
#include <beast/module/asio/HTTPMessage.cpp>
|
|
||||||
#include <beast/module/asio/HTTPRequest.cpp>
|
|
||||||
#include <beast/module/asio/HTTPResponse.cpp>
|
|
||||||
#include <beast/module/asio/HTTPVersion.cpp>
|
|
||||||
#include <beast/module/asio/HTTPParser.cpp>
|
|
||||||
#include <beast/module/asio/HTTPRequestParser.cpp>
|
|
||||||
#include <beast/module/asio/HTTPResponseParser.cpp>
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,135 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Portions of this file are from JUCE.
|
|
||||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
|
||||||
Please visit http://www.juce.com
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_MODULE_CORE_CONTAINERS_ARRAYALLOCATIONBASE_H_INCLUDED
|
|
||||||
#define BEAST_MODULE_CORE_CONTAINERS_ARRAYALLOCATIONBASE_H_INCLUDED
|
|
||||||
|
|
||||||
#include <beast/HeapBlock.h>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/**
|
|
||||||
Implements some basic array storage allocation functions.
|
|
||||||
|
|
||||||
This class isn't really for public use - it's used by the other
|
|
||||||
array classes, but might come in handy for some purposes.
|
|
||||||
|
|
||||||
It inherits from a critical section class to allow the arrays to use
|
|
||||||
the "empty base class optimisation" pattern to reduce their footprint.
|
|
||||||
|
|
||||||
@see Array, SharedObjectArray
|
|
||||||
*/
|
|
||||||
template <class ElementType, class TypeOfCriticalSectionToUse>
|
|
||||||
class ArrayAllocationBase
|
|
||||||
: public TypeOfCriticalSectionToUse
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//==============================================================================
|
|
||||||
/** Creates an empty array. */
|
|
||||||
ArrayAllocationBase() noexcept
|
|
||||||
: numAllocated (0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Destructor. */
|
|
||||||
~ArrayAllocationBase() noexcept
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
|
||||||
ArrayAllocationBase (ArrayAllocationBase<ElementType, TypeOfCriticalSectionToUse>&& other) noexcept
|
|
||||||
: elements (static_cast <HeapBlock <ElementType>&&> (other.elements)),
|
|
||||||
numAllocated (other.numAllocated)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayAllocationBase& operator= (ArrayAllocationBase<ElementType, TypeOfCriticalSectionToUse>&& other) noexcept
|
|
||||||
{
|
|
||||||
elements = static_cast <HeapBlock <ElementType>&&> (other.elements);
|
|
||||||
numAllocated = other.numAllocated;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Changes the amount of storage allocated.
|
|
||||||
|
|
||||||
This will retain any data currently held in the array, and either add or
|
|
||||||
remove extra space at the end.
|
|
||||||
|
|
||||||
@param numElements the number of elements that are needed
|
|
||||||
*/
|
|
||||||
void setAllocatedSize (const int numElements)
|
|
||||||
{
|
|
||||||
if (numAllocated != numElements)
|
|
||||||
{
|
|
||||||
if (numElements > 0)
|
|
||||||
elements.reallocate ((size_t) numElements);
|
|
||||||
else
|
|
||||||
elements.free_up();
|
|
||||||
|
|
||||||
numAllocated = numElements;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Increases the amount of storage allocated if it is less than a given amount.
|
|
||||||
|
|
||||||
This will retain any data currently held in the array, but will add
|
|
||||||
extra space at the end to make sure there it's at least as big as the size
|
|
||||||
passed in. If it's already bigger, no action is taken.
|
|
||||||
|
|
||||||
@param minNumElements the minimum number of elements that are needed
|
|
||||||
*/
|
|
||||||
void ensureAllocatedSize (const int minNumElements)
|
|
||||||
{
|
|
||||||
if (minNumElements > numAllocated)
|
|
||||||
setAllocatedSize ((minNumElements + minNumElements / 2 + 8) & ~7);
|
|
||||||
|
|
||||||
bassert (numAllocated <= 0 || elements != nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Minimises the amount of storage allocated so that it's no more than
|
|
||||||
the given number of elements.
|
|
||||||
*/
|
|
||||||
void shrinkToNoMoreThan (const int maxNumElements)
|
|
||||||
{
|
|
||||||
if (maxNumElements < numAllocated)
|
|
||||||
setAllocatedSize (maxNumElements);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Swap the contents of two objects. */
|
|
||||||
void swapWith (ArrayAllocationBase <ElementType, TypeOfCriticalSectionToUse>& other) noexcept
|
|
||||||
{
|
|
||||||
elements.swapWith (other.elements);
|
|
||||||
std::swap (numAllocated, other.numAllocated);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
HeapBlock <ElementType> elements;
|
|
||||||
int numAllocated;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
#endif // BEAST_ARRAYALLOCATIONBASE_H_INCLUDED
|
|
||||||
@@ -1,195 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Portions of this file are from JUCE.
|
|
||||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
|
||||||
Please visit http://www.juce.com
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_MODULE_CORE_CONTAINERS_ELEMENTCOMPARATOR_H_INCLUDED
|
|
||||||
#define BEAST_MODULE_CORE_CONTAINERS_ELEMENTCOMPARATOR_H_INCLUDED
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
#ifndef DOXYGEN
|
|
||||||
|
|
||||||
/** This is an internal helper class which converts a beast ElementComparator style
|
|
||||||
class (using a "compareElements" method) into a class that's compatible with
|
|
||||||
std::sort (i.e. using an operator() to compare the elements)
|
|
||||||
*/
|
|
||||||
template <typename ElementComparator>
|
|
||||||
struct SortFunctionConverter
|
|
||||||
{
|
|
||||||
SortFunctionConverter (ElementComparator& e) : comparator (e) {}
|
|
||||||
|
|
||||||
template <typename Type>
|
|
||||||
bool operator() (Type a, Type b) { return comparator.compareElements (a, b) < 0; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
ElementComparator& comparator;
|
|
||||||
SortFunctionConverter& operator= (const SortFunctionConverter&);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/**
|
|
||||||
Sorts a range of elements in an array.
|
|
||||||
|
|
||||||
The comparator object that is passed-in must define a public method with the following
|
|
||||||
signature:
|
|
||||||
@code
|
|
||||||
int compareElements (ElementType first, ElementType second);
|
|
||||||
@endcode
|
|
||||||
|
|
||||||
..and this method must return:
|
|
||||||
- a value of < 0 if the first comes before the second
|
|
||||||
- a value of 0 if the two objects are equivalent
|
|
||||||
- a value of > 0 if the second comes before the first
|
|
||||||
|
|
||||||
To improve performance, the compareElements() method can be declared as static or const.
|
|
||||||
|
|
||||||
@param comparator an object which defines a compareElements() method
|
|
||||||
@param array the array to sort
|
|
||||||
@param firstElement the index of the first element of the range to be sorted
|
|
||||||
@param lastElement the index of the last element in the range that needs
|
|
||||||
sorting (this is inclusive)
|
|
||||||
@param retainOrderOfEquivalentItems if true, the order of items that the
|
|
||||||
comparator deems the same will be maintained - this will be
|
|
||||||
a slower algorithm than if they are allowed to be moved around.
|
|
||||||
|
|
||||||
@see sortArrayRetainingOrder
|
|
||||||
*/
|
|
||||||
template <class ElementType, class ElementComparator>
|
|
||||||
static void sortArray (ElementComparator& comparator,
|
|
||||||
ElementType* const array,
|
|
||||||
int firstElement,
|
|
||||||
int lastElement,
|
|
||||||
const bool retainOrderOfEquivalentItems)
|
|
||||||
{
|
|
||||||
SortFunctionConverter<ElementComparator> converter (comparator);
|
|
||||||
|
|
||||||
if (retainOrderOfEquivalentItems)
|
|
||||||
std::stable_sort (array + firstElement, array + lastElement + 1, converter);
|
|
||||||
else
|
|
||||||
std::sort (array + firstElement, array + lastElement + 1, converter);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/**
|
|
||||||
Searches a sorted array of elements, looking for the index at which a specified value
|
|
||||||
should be inserted for it to be in the correct order.
|
|
||||||
|
|
||||||
The comparator object that is passed-in must define a public method with the following
|
|
||||||
signature:
|
|
||||||
@code
|
|
||||||
int compareElements (ElementType first, ElementType second);
|
|
||||||
@endcode
|
|
||||||
|
|
||||||
..and this method must return:
|
|
||||||
- a value of < 0 if the first comes before the second
|
|
||||||
- a value of 0 if the two objects are equivalent
|
|
||||||
- a value of > 0 if the second comes before the first
|
|
||||||
|
|
||||||
To improve performance, the compareElements() method can be declared as static or const.
|
|
||||||
|
|
||||||
@param comparator an object which defines a compareElements() method
|
|
||||||
@param array the array to search
|
|
||||||
@param newElement the value that is going to be inserted
|
|
||||||
@param firstElement the index of the first element to search
|
|
||||||
@param lastElement the index of the last element in the range (this is non-inclusive)
|
|
||||||
*/
|
|
||||||
template <class ElementType, class ElementComparator>
|
|
||||||
static int findInsertIndexInSortedArray (ElementComparator& comparator,
|
|
||||||
ElementType* const array,
|
|
||||||
const ElementType newElement,
|
|
||||||
int firstElement,
|
|
||||||
int lastElement)
|
|
||||||
{
|
|
||||||
bassert (firstElement <= lastElement);
|
|
||||||
|
|
||||||
(void) comparator; // if you pass in an object with a static compareElements() method, this
|
|
||||||
// avoids getting warning messages about the parameter being unused
|
|
||||||
|
|
||||||
while (firstElement < lastElement)
|
|
||||||
{
|
|
||||||
if (comparator.compareElements (newElement, array [firstElement]) == 0)
|
|
||||||
{
|
|
||||||
++firstElement;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const int halfway = (firstElement + lastElement) >> 1;
|
|
||||||
|
|
||||||
if (halfway == firstElement)
|
|
||||||
{
|
|
||||||
if (comparator.compareElements (newElement, array [halfway]) >= 0)
|
|
||||||
++firstElement;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (comparator.compareElements (newElement, array [halfway]) >= 0)
|
|
||||||
{
|
|
||||||
firstElement = halfway;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lastElement = halfway;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return firstElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/**
|
|
||||||
A simple ElementComparator class that can be used to sort an array of
|
|
||||||
objects that support the '<' operator.
|
|
||||||
|
|
||||||
This will work for primitive types and objects that implement operator<().
|
|
||||||
|
|
||||||
Example: @code
|
|
||||||
Array <int> myArray;
|
|
||||||
DefaultElementComparator<int> sorter;
|
|
||||||
myArray.sort (sorter);
|
|
||||||
@endcode
|
|
||||||
|
|
||||||
@see ElementComparator
|
|
||||||
*/
|
|
||||||
template <class ElementType>
|
|
||||||
class DefaultElementComparator
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
using ParameterType = ElementType;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static int compareElements (ParameterType first, ParameterType second)
|
|
||||||
{
|
|
||||||
return (first < second) ? -1 : ((second < first) ? 1 : 0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -26,7 +26,6 @@
|
|||||||
|
|
||||||
// TargetPlatform.h should not use anything from BeastConfig.h
|
// TargetPlatform.h should not use anything from BeastConfig.h
|
||||||
#include <beast/Config.h>
|
#include <beast/Config.h>
|
||||||
#include <beast/config/ContractChecks.h>
|
|
||||||
|
|
||||||
#if BEAST_MSVC
|
#if BEAST_MSVC
|
||||||
# pragma warning (disable: 4251) // (DLL build warning, must be disabled before pushing the warning state)
|
# pragma warning (disable: 4251) // (DLL build warning, must be disabled before pushing the warning state)
|
||||||
@@ -41,12 +40,10 @@
|
|||||||
|
|
||||||
// New header-only library modeled more closely according to boost
|
// New header-only library modeled more closely according to boost
|
||||||
#include <beast/SmartPtr.h>
|
#include <beast/SmartPtr.h>
|
||||||
#include <beast/Arithmetic.h>
|
|
||||||
#include <beast/ByteOrder.h>
|
#include <beast/ByteOrder.h>
|
||||||
#include <beast/HeapBlock.h>
|
#include <beast/HeapBlock.h>
|
||||||
#include <beast/Memory.h>
|
#include <beast/Memory.h>
|
||||||
#include <beast/Intrusive.h>
|
#include <beast/Intrusive.h>
|
||||||
#include <beast/Strings.h>
|
|
||||||
#include <beast/Threads.h>
|
#include <beast/Threads.h>
|
||||||
|
|
||||||
#include <beast/utility/Debug.h>
|
#include <beast/utility/Debug.h>
|
||||||
@@ -55,91 +52,14 @@
|
|||||||
|
|
||||||
#include <beast/module/core/system/StandardIncludes.h>
|
#include <beast/module/core/system/StandardIncludes.h>
|
||||||
|
|
||||||
namespace beast
|
|
||||||
{
|
|
||||||
|
|
||||||
class InputStream;
|
|
||||||
class OutputStream;
|
|
||||||
class FileInputStream;
|
|
||||||
class FileOutputStream;
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
// Order matters, since headers don't have their own #include lines.
|
// Order matters, since headers don't have their own #include lines.
|
||||||
// Add new includes to the bottom.
|
// Add new includes to the bottom.
|
||||||
|
|
||||||
#include <beast/module/core/time/Time.h>
|
|
||||||
#include <beast/module/core/threads/ScopedLock.h>
|
#include <beast/module/core/threads/ScopedLock.h>
|
||||||
#include <beast/module/core/threads/CriticalSection.h>
|
|
||||||
#include <beast/module/core/containers/ElementComparator.h>
|
|
||||||
|
|
||||||
// If the MSVC debug heap headers were included, disable
|
|
||||||
// the macros during the juce include since they conflict.
|
|
||||||
#ifdef _CRTDBG_MAP_ALLOC
|
|
||||||
#pragma push_macro("calloc")
|
|
||||||
#pragma push_macro("free")
|
|
||||||
#pragma push_macro("malloc")
|
|
||||||
#pragma push_macro("realloc")
|
|
||||||
#pragma push_macro("_recalloc")
|
|
||||||
#pragma push_macro("_aligned_free")
|
|
||||||
#pragma push_macro("_aligned_malloc")
|
|
||||||
#pragma push_macro("_aligned_offset_malloc")
|
|
||||||
#pragma push_macro("_aligned_realloc")
|
|
||||||
#pragma push_macro("_aligned_recalloc")
|
|
||||||
#pragma push_macro("_aligned_offset_realloc")
|
|
||||||
#pragma push_macro("_aligned_offset_recalloc")
|
|
||||||
#pragma push_macro("_aligned_msize")
|
|
||||||
#undef calloc
|
|
||||||
#undef free
|
|
||||||
#undef malloc
|
|
||||||
#undef realloc
|
|
||||||
#undef _recalloc
|
|
||||||
#undef _aligned_free
|
|
||||||
#undef _aligned_malloc
|
|
||||||
#undef _aligned_offset_malloc
|
|
||||||
#undef _aligned_realloc
|
|
||||||
#undef _aligned_recalloc
|
|
||||||
#undef _aligned_offset_realloc
|
|
||||||
#undef _aligned_offset_recalloc
|
|
||||||
#undef _aligned_msize
|
|
||||||
#endif
|
|
||||||
#include <beast/module/core/containers/ArrayAllocationBase.h>
|
|
||||||
#ifdef _CRTDBG_MAP_ALLOC
|
|
||||||
#pragma pop_macro("_aligned_msize")
|
|
||||||
#pragma pop_macro("_aligned_offset_recalloc")
|
|
||||||
#pragma pop_macro("_aligned_offset_realloc")
|
|
||||||
#pragma pop_macro("_aligned_recalloc")
|
|
||||||
#pragma pop_macro("_aligned_realloc")
|
|
||||||
#pragma pop_macro("_aligned_offset_malloc")
|
|
||||||
#pragma pop_macro("_aligned_malloc")
|
|
||||||
#pragma pop_macro("_aligned_free")
|
|
||||||
#pragma pop_macro("_recalloc")
|
|
||||||
#pragma pop_macro("realloc")
|
|
||||||
#pragma pop_macro("malloc")
|
|
||||||
#pragma pop_macro("free")
|
|
||||||
#pragma pop_macro("calloc")
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <beast/module/core/containers/Array.h>
|
|
||||||
|
|
||||||
#include <beast/module/core/misc/Result.h>
|
|
||||||
#include <beast/module/core/text/StringArray.h>
|
|
||||||
#include <beast/module/core/memory/MemoryBlock.h>
|
|
||||||
#include <beast/module/core/files/File.h>
|
|
||||||
|
|
||||||
#include <beast/module/core/thread/MutexTraits.h>
|
|
||||||
#include <beast/module/core/diagnostic/FatalError.h>
|
#include <beast/module/core/diagnostic/FatalError.h>
|
||||||
#include <beast/module/core/text/LexicalCast.h>
|
#include <beast/module/core/text/LexicalCast.h>
|
||||||
#include <beast/module/core/logging/Logger.h>
|
#include <beast/module/core/logging/Logger.h>
|
||||||
#include <beast/module/core/maths/Random.h>
|
|
||||||
#include <beast/module/core/text/StringPairArray.h>
|
|
||||||
#include <beast/module/core/files/DirectoryIterator.h>
|
|
||||||
#include <beast/module/core/streams/InputStream.h>
|
|
||||||
#include <beast/module/core/files/FileInputStream.h>
|
|
||||||
#include <beast/module/core/streams/InputSource.h>
|
|
||||||
#include <beast/module/core/streams/OutputStream.h>
|
|
||||||
#include <beast/module/core/files/FileOutputStream.h>
|
|
||||||
#include <beast/module/core/streams/MemoryOutputStream.h>
|
|
||||||
|
|
||||||
#include <beast/module/core/system/SystemStats.h>
|
#include <beast/module/core/system/SystemStats.h>
|
||||||
#include <beast/module/core/diagnostic/SemanticVersion.h>
|
#include <beast/module/core/diagnostic/SemanticVersion.h>
|
||||||
|
|||||||
@@ -134,26 +134,9 @@
|
|||||||
#include <beast/module/core/diagnostic/SemanticVersion.cpp>
|
#include <beast/module/core/diagnostic/SemanticVersion.cpp>
|
||||||
#include <beast/module/core/diagnostic/UnitTestUtilities.cpp>
|
#include <beast/module/core/diagnostic/UnitTestUtilities.cpp>
|
||||||
|
|
||||||
#include <beast/module/core/files/DirectoryIterator.cpp>
|
|
||||||
#include <beast/module/core/files/File.cpp>
|
|
||||||
#include <beast/module/core/files/FileInputStream.cpp>
|
|
||||||
#include <beast/module/core/files/FileOutputStream.cpp>
|
|
||||||
|
|
||||||
#include <beast/module/core/maths/Random.cpp>
|
|
||||||
|
|
||||||
#include <beast/module/core/memory/MemoryBlock.cpp>
|
|
||||||
|
|
||||||
#include <beast/module/core/misc/Result.cpp>
|
|
||||||
|
|
||||||
#include <beast/module/core/streams/InputStream.cpp>
|
|
||||||
#include <beast/module/core/streams/MemoryOutputStream.cpp>
|
|
||||||
#include <beast/module/core/streams/OutputStream.cpp>
|
|
||||||
|
|
||||||
#include <beast/module/core/system/SystemStats.cpp>
|
#include <beast/module/core/system/SystemStats.cpp>
|
||||||
|
|
||||||
#include <beast/module/core/text/LexicalCast.cpp>
|
#include <beast/module/core/text/LexicalCast.cpp>
|
||||||
#include <beast/module/core/text/StringArray.cpp>
|
|
||||||
#include <beast/module/core/text/StringPairArray.cpp>
|
|
||||||
|
|
||||||
#include <beast/module/core/thread/DeadlineTimer.cpp>
|
#include <beast/module/core/thread/DeadlineTimer.cpp>
|
||||||
#include <beast/module/core/thread/Workers.cpp>
|
#include <beast/module/core/thread/Workers.cpp>
|
||||||
@@ -168,26 +151,16 @@
|
|||||||
#include "native/android_JNIHelpers.h"
|
#include "native/android_JNIHelpers.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ! BEAST_WINDOWS
|
|
||||||
#include <beast/module/core/native/posix_SharedCode.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if BEAST_MAC || BEAST_IOS
|
#if BEAST_MAC || BEAST_IOS
|
||||||
#include <beast/module/core/native/mac_Files.mm>
|
|
||||||
#include <beast/module/core/native/mac_Strings.mm>
|
|
||||||
#include <beast/module/core/native/mac_SystemStats.mm>
|
#include <beast/module/core/native/mac_SystemStats.mm>
|
||||||
|
|
||||||
#elif BEAST_WINDOWS
|
#elif BEAST_WINDOWS
|
||||||
#include <beast/module/core/native/win32_Files.cpp>
|
|
||||||
#include <beast/module/core/native/win32_SystemStats.cpp>
|
#include <beast/module/core/native/win32_SystemStats.cpp>
|
||||||
#include <beast/module/core/native/win32_Threads.cpp>
|
|
||||||
|
|
||||||
#elif BEAST_LINUX
|
#elif BEAST_LINUX
|
||||||
#include <beast/module/core/native/linux_Files.cpp>
|
|
||||||
#include <beast/module/core/native/linux_SystemStats.cpp>
|
#include <beast/module/core/native/linux_SystemStats.cpp>
|
||||||
|
|
||||||
#elif BEAST_BSD
|
#elif BEAST_BSD
|
||||||
#include <beast/module/core/native/bsd_Files.cpp>
|
|
||||||
#include <beast/module/core/native/bsd_SystemStats.cpp>
|
#include <beast/module/core/native/bsd_SystemStats.cpp>
|
||||||
|
|
||||||
#elif BEAST_ANDROID
|
#elif BEAST_ANDROID
|
||||||
@@ -198,17 +171,6 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Has to be outside the beast namespace
|
|
||||||
extern "C" {
|
|
||||||
void beast_reportFatalError (char const* message, char const* fileName, int lineNumber)
|
|
||||||
{
|
|
||||||
if (beast::beast_isRunningUnderDebugger())
|
|
||||||
beast_breakDebugger;
|
|
||||||
beast::FatalError (message, fileName, lineNumber);
|
|
||||||
BEAST_ANALYZER_NORETURN
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _CRTDBG_MAP_ALLOC
|
#ifdef _CRTDBG_MAP_ALLOC
|
||||||
#pragma pop_macro("calloc")
|
#pragma pop_macro("calloc")
|
||||||
#pragma pop_macro("free")
|
#pragma pop_macro("free")
|
||||||
|
|||||||
@@ -20,8 +20,6 @@
|
|||||||
#ifndef BEAST_MODULE_CORE_DIAGNOSTIC_FATALERROR_H_INCLUDED
|
#ifndef BEAST_MODULE_CORE_DIAGNOSTIC_FATALERROR_H_INCLUDED
|
||||||
#define BEAST_MODULE_CORE_DIAGNOSTIC_FATALERROR_H_INCLUDED
|
#define BEAST_MODULE_CORE_DIAGNOSTIC_FATALERROR_H_INCLUDED
|
||||||
|
|
||||||
#include <beast/strings/String.h>
|
|
||||||
|
|
||||||
namespace beast
|
namespace beast
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include <beast/module/core/text/LexicalCast.h>
|
#include <beast/module/core/text/LexicalCast.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
@@ -291,7 +292,7 @@ int compare (SemanticVersion const& lhs, SemanticVersion const& rhs)
|
|||||||
|
|
||||||
if (isNumeric (left))
|
if (isNumeric (left))
|
||||||
{
|
{
|
||||||
bassert (isNumeric (right));
|
assert(isNumeric (right));
|
||||||
|
|
||||||
int const iLeft (lexicalCastThrow <int> (left));
|
int const iLeft (lexicalCastThrow <int> (left));
|
||||||
int const iRight (lexicalCastThrow <int> (right));
|
int const iRight (lexicalCastThrow <int> (right));
|
||||||
@@ -303,7 +304,7 @@ int compare (SemanticVersion const& lhs, SemanticVersion const& rhs)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bassert (! isNumeric (right));
|
assert (! isNumeric (right));
|
||||||
|
|
||||||
int result = left.compare (right);
|
int result = left.compare (right);
|
||||||
|
|
||||||
|
|||||||
@@ -20,111 +20,51 @@
|
|||||||
#ifndef BEAST_MODULE_CORE_DIAGNOSTIC_UNITTESTUTILITIES_H_INCLUDED
|
#ifndef BEAST_MODULE_CORE_DIAGNOSTIC_UNITTESTUTILITIES_H_INCLUDED
|
||||||
#define BEAST_MODULE_CORE_DIAGNOSTIC_UNITTESTUTILITIES_H_INCLUDED
|
#define BEAST_MODULE_CORE_DIAGNOSTIC_UNITTESTUTILITIES_H_INCLUDED
|
||||||
|
|
||||||
#include <beast/module/core/files/File.h>
|
#include <boost/filesystem.hpp>
|
||||||
#include <beast/module/core/maths/Random.h>
|
#include <string>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace UnitTestUtilities {
|
namespace UnitTestUtilities {
|
||||||
|
|
||||||
/** Fairly shuffle an array pseudo-randomly.
|
|
||||||
*/
|
|
||||||
template <class T>
|
|
||||||
void repeatableShuffle (int const numberOfItems, T& arrayOfItems, Random& r)
|
|
||||||
{
|
|
||||||
for (int i = numberOfItems - 1; i > 0; --i)
|
|
||||||
{
|
|
||||||
int const choice = r.nextInt (i + 1);
|
|
||||||
std::swap (arrayOfItems [i], arrayOfItems [choice]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
void repeatableShuffle (int const numberOfItems, T& arrayOfItems, std::int64_t seedValue)
|
|
||||||
{
|
|
||||||
Random r (seedValue);
|
|
||||||
repeatableShuffle (numberOfItems, arrayOfItems, r);
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/** A block of memory used for test data.
|
|
||||||
*/
|
|
||||||
struct Payload
|
|
||||||
{
|
|
||||||
/** Construct a payload with a buffer of the specified maximum size.
|
|
||||||
|
|
||||||
@param maximumBytes The size of the buffer, in bytes.
|
|
||||||
*/
|
|
||||||
explicit Payload (int maxBufferSize)
|
|
||||||
: bufferSize (maxBufferSize)
|
|
||||||
, data (maxBufferSize)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Generate a random block of data within a certain size range.
|
|
||||||
|
|
||||||
@param minimumBytes The smallest number of bytes in the resulting payload.
|
|
||||||
@param maximumBytes The largest number of bytes in the resulting payload.
|
|
||||||
@param seedValue The value to seed the random number generator with.
|
|
||||||
*/
|
|
||||||
void repeatableRandomFill (int minimumBytes, int maximumBytes, std::int64_t seedValue) noexcept
|
|
||||||
{
|
|
||||||
bassert (minimumBytes >=0 && maximumBytes <= bufferSize);
|
|
||||||
|
|
||||||
Random r (seedValue);
|
|
||||||
|
|
||||||
bytes = minimumBytes + r.nextInt (1 + maximumBytes - minimumBytes);
|
|
||||||
|
|
||||||
bassert (bytes >= minimumBytes && bytes <= bufferSize);
|
|
||||||
|
|
||||||
for (int i = 0; i < bytes; ++i)
|
|
||||||
data [i] = static_cast <unsigned char> (r.nextInt ());
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Compare two payloads for equality.
|
|
||||||
*/
|
|
||||||
bool operator== (Payload const& other) const noexcept
|
|
||||||
{
|
|
||||||
if (bytes == other.bytes)
|
|
||||||
{
|
|
||||||
return memcmp (data.getData (), other.data.getData (), bytes) == 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
int const bufferSize;
|
|
||||||
|
|
||||||
int bytes;
|
|
||||||
HeapBlock <char> data;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TempDirectory
|
class TempDirectory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit TempDirectory (std::string const& root)
|
TempDirectory ()
|
||||||
: directory (File::createTempFile (root))
|
|
||||||
{
|
{
|
||||||
|
auto const tempDir =
|
||||||
|
boost::filesystem::temp_directory_path();
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
tempPath =
|
||||||
|
tempDir / boost::filesystem::unique_path();
|
||||||
|
} while (boost::filesystem::exists(tempPath));
|
||||||
|
|
||||||
|
boost::filesystem::create_directory (tempPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
~TempDirectory()
|
~TempDirectory()
|
||||||
{
|
{
|
||||||
directory.deleteRecursively();
|
boost::filesystem::remove_all (tempPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
String const& getFullPathName() const
|
/** Returns the native path for the temporary folder */
|
||||||
|
std::string path() const
|
||||||
{
|
{
|
||||||
return directory.getFullPathName();
|
return tempPath.string();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the native for the given file */
|
||||||
|
std::string file (std::string const& name) const
|
||||||
|
{
|
||||||
|
return (tempPath / name).string();
|
||||||
}
|
}
|
||||||
|
|
||||||
TempDirectory(const TempDirectory&) = delete;
|
TempDirectory(const TempDirectory&) = delete;
|
||||||
TempDirectory& operator=(const TempDirectory&) = delete;
|
TempDirectory& operator=(const TempDirectory&) = delete;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
File const directory;
|
boost::filesystem::path tempPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // UnitTestUtilities
|
} // UnitTestUtilities
|
||||||
|
|||||||
@@ -1,161 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Portions of this file are from JUCE.
|
|
||||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
|
||||||
Please visit http://www.juce.com
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
static StringArray parseWildcards (const String& pattern)
|
|
||||||
{
|
|
||||||
StringArray s;
|
|
||||||
s.addTokens (pattern, ";,", "\"'");
|
|
||||||
s.trim();
|
|
||||||
s.removeEmptyStrings();
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool fileMatches (const StringArray& wildCards, const String& filename)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < wildCards.size(); ++i)
|
|
||||||
if (filename.matchesWildcard (wildCards[i], ! File::areFileNamesCaseSensitive()))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DirectoryIterator::DirectoryIterator (const File& directory, bool recursive,
|
|
||||||
const String& pattern, const int type)
|
|
||||||
: wildCards (parseWildcards (pattern)),
|
|
||||||
fileFinder (directory, (recursive || wildCards.size() > 1) ? "*" : pattern),
|
|
||||||
wildCard (pattern),
|
|
||||||
path (File::addTrailingSeparator (directory.getFullPathName())),
|
|
||||||
index (-1),
|
|
||||||
totalNumFiles (-1),
|
|
||||||
whatToLookFor (type),
|
|
||||||
isRecursive (recursive),
|
|
||||||
hasBeenAdvanced (false)
|
|
||||||
{
|
|
||||||
// you have to specify the type of files you're looking for!
|
|
||||||
bassert ((type & (File::findFiles | File::findDirectories)) != 0);
|
|
||||||
bassert (type > 0 && type <= 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
DirectoryIterator::~DirectoryIterator()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DirectoryIterator::next()
|
|
||||||
{
|
|
||||||
return next (nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DirectoryIterator::next (bool* const isDirResult, bool* const isHiddenResult, std::int64_t* const fileSize,
|
|
||||||
Time* const modTime, Time* const creationTime, bool* const isReadOnly)
|
|
||||||
{
|
|
||||||
hasBeenAdvanced = true;
|
|
||||||
|
|
||||||
if (subIterator != nullptr)
|
|
||||||
{
|
|
||||||
if (subIterator->next (isDirResult, isHiddenResult, fileSize, modTime, creationTime, isReadOnly))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
subIterator = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
String filename;
|
|
||||||
bool isDirectory, isHidden = false;
|
|
||||||
|
|
||||||
while (fileFinder.next (filename, &isDirectory,
|
|
||||||
(isHiddenResult != nullptr || (whatToLookFor & File::ignoreHiddenFiles) != 0) ? &isHidden : nullptr,
|
|
||||||
fileSize, modTime, creationTime, isReadOnly))
|
|
||||||
{
|
|
||||||
++index;
|
|
||||||
|
|
||||||
if (! filename.containsOnly ("."))
|
|
||||||
{
|
|
||||||
bool matches = false;
|
|
||||||
|
|
||||||
if (isDirectory)
|
|
||||||
{
|
|
||||||
if (isRecursive && ((whatToLookFor & File::ignoreHiddenFiles) == 0 || ! isHidden))
|
|
||||||
subIterator = std::make_unique <DirectoryIterator> (
|
|
||||||
File::createFileWithoutCheckingPath (path + filename),
|
|
||||||
true, wildCard, whatToLookFor);
|
|
||||||
|
|
||||||
matches = (whatToLookFor & File::findDirectories) != 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
matches = (whatToLookFor & File::findFiles) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we're not relying on the OS iterator to do the wildcard match, do it now..
|
|
||||||
if (matches && (isRecursive || wildCards.size() > 1))
|
|
||||||
matches = fileMatches (wildCards, filename);
|
|
||||||
|
|
||||||
if (matches && (whatToLookFor & File::ignoreHiddenFiles) != 0)
|
|
||||||
matches = ! isHidden;
|
|
||||||
|
|
||||||
if (matches)
|
|
||||||
{
|
|
||||||
currentFile = File::createFileWithoutCheckingPath (path + filename);
|
|
||||||
if (isHiddenResult != nullptr) *isHiddenResult = isHidden;
|
|
||||||
if (isDirResult != nullptr) *isDirResult = isDirectory;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (subIterator != nullptr)
|
|
||||||
return next (isDirResult, isHiddenResult, fileSize, modTime, creationTime, isReadOnly);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const File& DirectoryIterator::getFile() const
|
|
||||||
{
|
|
||||||
if (subIterator != nullptr && subIterator->hasBeenAdvanced)
|
|
||||||
return subIterator->getFile();
|
|
||||||
|
|
||||||
// You need to call DirectoryIterator::next() before asking it for the file that it found!
|
|
||||||
bassert (hasBeenAdvanced);
|
|
||||||
|
|
||||||
return currentFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
float DirectoryIterator::getEstimatedProgress() const
|
|
||||||
{
|
|
||||||
if (totalNumFiles < 0)
|
|
||||||
totalNumFiles = File (path).getNumberOfChildFiles (File::findFilesAndDirectories);
|
|
||||||
|
|
||||||
if (totalNumFiles <= 0)
|
|
||||||
return 0.0f;
|
|
||||||
|
|
||||||
const float detailedIndex = (subIterator != nullptr) ? index + subIterator->getEstimatedProgress()
|
|
||||||
: (float) index;
|
|
||||||
|
|
||||||
return detailedIndex / totalNumFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
@@ -1,157 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Portions of this file are from JUCE.
|
|
||||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
|
||||||
Please visit http://www.juce.com
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_MODULE_CORE_FILES_DIRECTORYITERATOR_H_INCLUDED
|
|
||||||
#define BEAST_MODULE_CORE_FILES_DIRECTORYITERATOR_H_INCLUDED
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/**
|
|
||||||
Searches through a the files in a directory, returning each file that is found.
|
|
||||||
|
|
||||||
A DirectoryIterator will search through a directory and its subdirectories using
|
|
||||||
a wildcard filepattern match.
|
|
||||||
|
|
||||||
If you may be finding a large number of files, this is better than
|
|
||||||
using File::findChildFiles() because it doesn't block while it finds them
|
|
||||||
all, and this is more memory-efficient.
|
|
||||||
|
|
||||||
It can also guess how far it's got using a wildly inaccurate algorithm.
|
|
||||||
*/
|
|
||||||
class DirectoryIterator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//==============================================================================
|
|
||||||
/** Creates a DirectoryIterator for a given directory.
|
|
||||||
|
|
||||||
After creating one of these, call its next() method to get the
|
|
||||||
first file - e.g. @code
|
|
||||||
|
|
||||||
DirectoryIterator iter (File ("/animals/mooses"), true, "*.moose");
|
|
||||||
|
|
||||||
while (iter.next())
|
|
||||||
{
|
|
||||||
File theFileItFound (iter.getFile());
|
|
||||||
|
|
||||||
... etc
|
|
||||||
}
|
|
||||||
@endcode
|
|
||||||
|
|
||||||
@param directory the directory to search in
|
|
||||||
@param isRecursive whether all the subdirectories should also be searched
|
|
||||||
@param wildCard the file pattern to match. This may contain multiple patterns
|
|
||||||
separated by a semi-colon or comma, e.g. "*.jpg;*.png"
|
|
||||||
@param whatToLookFor a value from the File::TypesOfFileToFind enum, specifying
|
|
||||||
whether to look for files, directories, or both.
|
|
||||||
*/
|
|
||||||
DirectoryIterator (const File& directory,
|
|
||||||
bool isRecursive,
|
|
||||||
const String& wildCard = "*",
|
|
||||||
int whatToLookFor = File::findFiles);
|
|
||||||
|
|
||||||
DirectoryIterator(DirectoryIterator const&) = delete;
|
|
||||||
DirectoryIterator& operator= (DirectoryIterator const&) = delete;
|
|
||||||
|
|
||||||
/** Destructor. */
|
|
||||||
~DirectoryIterator();
|
|
||||||
|
|
||||||
/** Moves the iterator along to the next file.
|
|
||||||
|
|
||||||
@returns true if a file was found (you can then use getFile() to see what it was) - or
|
|
||||||
false if there are no more matching files.
|
|
||||||
*/
|
|
||||||
bool next();
|
|
||||||
|
|
||||||
/** Moves the iterator along to the next file, and returns various properties of that file.
|
|
||||||
|
|
||||||
If you need to find out details about the file, it's more efficient to call this method than
|
|
||||||
to call the normal next() method and then find out the details afterwards.
|
|
||||||
|
|
||||||
All the parameters are optional, so pass null pointers for any items that you're not
|
|
||||||
interested in.
|
|
||||||
|
|
||||||
@returns true if a file was found (you can then use getFile() to see what it was) - or
|
|
||||||
false if there are no more matching files. If it returns false, then none of the
|
|
||||||
parameters will be filled-in.
|
|
||||||
*/
|
|
||||||
bool next (bool* isDirectory,
|
|
||||||
bool* isHidden,
|
|
||||||
std::int64_t* fileSize,
|
|
||||||
Time* modTime,
|
|
||||||
Time* creationTime,
|
|
||||||
bool* isReadOnly);
|
|
||||||
|
|
||||||
/** Returns the file that the iterator is currently pointing at.
|
|
||||||
|
|
||||||
The result of this call is only valid after a call to next() has returned true.
|
|
||||||
*/
|
|
||||||
const File& getFile() const;
|
|
||||||
|
|
||||||
/** Returns a guess of how far through the search the iterator has got.
|
|
||||||
|
|
||||||
@returns a value 0.0 to 1.0 to show the progress, although this won't be
|
|
||||||
very accurate.
|
|
||||||
*/
|
|
||||||
float getEstimatedProgress() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
//==============================================================================
|
|
||||||
class NativeIterator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NativeIterator (const File& directory, const String& wildCard);
|
|
||||||
|
|
||||||
NativeIterator(NativeIterator const&) = delete;
|
|
||||||
NativeIterator& operator= (NativeIterator const&) = delete;
|
|
||||||
|
|
||||||
~NativeIterator();
|
|
||||||
|
|
||||||
bool next (String& filenameFound,
|
|
||||||
bool* isDirectory, bool* isHidden, std::int64_t* fileSize,
|
|
||||||
Time* modTime, Time* creationTime, bool* isReadOnly);
|
|
||||||
|
|
||||||
class Pimpl;
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class DirectoryIterator;
|
|
||||||
std::unique_ptr<Pimpl> pimpl;
|
|
||||||
};
|
|
||||||
|
|
||||||
StringArray wildCards;
|
|
||||||
NativeIterator fileFinder;
|
|
||||||
String wildCard, path;
|
|
||||||
int index;
|
|
||||||
mutable int totalNumFiles;
|
|
||||||
const int whatToLookFor;
|
|
||||||
const bool isRecursive;
|
|
||||||
bool hasBeenAdvanced;
|
|
||||||
std::unique_ptr <DirectoryIterator> subIterator;
|
|
||||||
File currentFile;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
#endif // BEAST_DIRECTORYITERATOR_H_INCLUDED
|
|
||||||
@@ -1,525 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Portions of this file are from JUCE.
|
|
||||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
|
||||||
Please visit http://www.juce.com
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
File const& File::nonexistent()
|
|
||||||
{
|
|
||||||
static File const instance;
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
File::File (const String& fullPathName)
|
|
||||||
: fullPath (parseAbsolutePath (fullPathName))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
File::File (const File& other)
|
|
||||||
: fullPath (other.fullPath)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
File File::createFileWithoutCheckingPath (const String& path) noexcept
|
|
||||||
{
|
|
||||||
File f;
|
|
||||||
f.fullPath = path;
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
File& File::operator= (const String& newPath)
|
|
||||||
{
|
|
||||||
fullPath = parseAbsolutePath (newPath);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
File& File::operator= (const File& other)
|
|
||||||
{
|
|
||||||
fullPath = other.fullPath;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
|
||||||
File::File (File&& other) noexcept
|
|
||||||
: fullPath (static_cast <String&&> (other.fullPath))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
File& File::operator= (File&& other) noexcept
|
|
||||||
{
|
|
||||||
fullPath = static_cast <String&&> (other.fullPath);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
String File::parseAbsolutePath (const String& p)
|
|
||||||
{
|
|
||||||
if (p.isEmpty())
|
|
||||||
return String::empty;
|
|
||||||
|
|
||||||
#if BEAST_WINDOWS
|
|
||||||
// Windows..
|
|
||||||
String path (p.replaceCharacter ('/', '\\'));
|
|
||||||
|
|
||||||
if (path.startsWithChar (separator))
|
|
||||||
{
|
|
||||||
if (path[1] != separator)
|
|
||||||
{
|
|
||||||
/* When you supply a raw string to the File object constructor, it must be an absolute path.
|
|
||||||
If you're trying to parse a string that may be either a relative path or an absolute path,
|
|
||||||
you MUST provide a context against which the partial path can be evaluated - you can do
|
|
||||||
this by simply using File::getChildFile() instead of the File constructor. E.g. saying
|
|
||||||
"File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
|
|
||||||
path if that's what was supplied, or would evaluate a partial path relative to the CWD.
|
|
||||||
*/
|
|
||||||
bassertfalse;
|
|
||||||
|
|
||||||
path = File::getCurrentWorkingDirectory().getFullPathName().substring (0, 2) + path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (! path.containsChar (':'))
|
|
||||||
{
|
|
||||||
/* When you supply a raw string to the File object constructor, it must be an absolute path.
|
|
||||||
If you're trying to parse a string that may be either a relative path or an absolute path,
|
|
||||||
you MUST provide a context against which the partial path can be evaluated - you can do
|
|
||||||
this by simply using File::getChildFile() instead of the File constructor. E.g. saying
|
|
||||||
"File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
|
|
||||||
path if that's what was supplied, or would evaluate a partial path relative to the CWD.
|
|
||||||
*/
|
|
||||||
bassertfalse;
|
|
||||||
|
|
||||||
return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
// Mac or Linux..
|
|
||||||
|
|
||||||
// Yes, I know it's legal for a unix pathname to contain a backslash, but this assertion is here
|
|
||||||
// to catch anyone who's trying to run code that was written on Windows with hard-coded path names.
|
|
||||||
// If that's why you've ended up here, use File::getChildFile() to build your paths instead.
|
|
||||||
bassert ((! p.containsChar ('\\')) || (p.indexOfChar ('/') >= 0 && p.indexOfChar ('/') < p.indexOfChar ('\\')));
|
|
||||||
|
|
||||||
String path (p);
|
|
||||||
|
|
||||||
if (path.startsWithChar ('~'))
|
|
||||||
{
|
|
||||||
if (path[1] == separator || path[1] == 0)
|
|
||||||
{
|
|
||||||
// expand a name of the form "~/abc"
|
|
||||||
path = File::getSpecialLocation (File::userHomeDirectory).getFullPathName()
|
|
||||||
+ path.substring (1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// expand a name of type "~dave/abc"
|
|
||||||
const String userName (path.substring (1).upToFirstOccurrenceOf ("/", false, false));
|
|
||||||
|
|
||||||
if (struct passwd* const pw = getpwnam (userName.toUTF8()))
|
|
||||||
path = addTrailingSeparator (pw->pw_dir) + path.fromFirstOccurrenceOf ("/", false, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (! path.startsWithChar (separator))
|
|
||||||
{
|
|
||||||
#if BEAST_DEBUG || BEAST_LOG_ASSERTIONS
|
|
||||||
if (! (path.startsWith ("./") || path.startsWith ("../")))
|
|
||||||
{
|
|
||||||
/* When you supply a raw string to the File object constructor, it must be an absolute path.
|
|
||||||
If you're trying to parse a string that may be either a relative path or an absolute path,
|
|
||||||
you MUST provide a context against which the partial path can be evaluated - you can do
|
|
||||||
this by simply using File::getChildFile() instead of the File constructor. E.g. saying
|
|
||||||
"File::getCurrentWorkingDirectory().getChildFile (myUnknownPath)" would return an absolute
|
|
||||||
path if that's what was supplied, or would evaluate a partial path relative to the CWD.
|
|
||||||
*/
|
|
||||||
bassertfalse;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return File::getCurrentWorkingDirectory().getChildFile (path).getFullPathName();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while (path.endsWithChar (separator) && path != separatorString) // careful not to turn a single "/" into an empty string.
|
|
||||||
path = path.dropLastCharacters (1);
|
|
||||||
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
String File::addTrailingSeparator (const String& path)
|
|
||||||
{
|
|
||||||
return path.endsWithChar (separator) ? path
|
|
||||||
: path + separator;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
#if BEAST_LINUX
|
|
||||||
#define NAMES_ARE_CASE_SENSITIVE 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool File::areFileNamesCaseSensitive()
|
|
||||||
{
|
|
||||||
#if NAMES_ARE_CASE_SENSITIVE
|
|
||||||
return true;
|
|
||||||
#else
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static int compareFilenames (const String& name1, const String& name2) noexcept
|
|
||||||
{
|
|
||||||
#if NAMES_ARE_CASE_SENSITIVE
|
|
||||||
return name1.compare (name2);
|
|
||||||
#else
|
|
||||||
return name1.compareIgnoreCase (name2);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool File::operator== (const File& other) const { return compareFilenames (fullPath, other.fullPath) == 0; }
|
|
||||||
bool File::operator!= (const File& other) const { return compareFilenames (fullPath, other.fullPath) != 0; }
|
|
||||||
bool File::operator< (const File& other) const { return compareFilenames (fullPath, other.fullPath) < 0; }
|
|
||||||
bool File::operator> (const File& other) const { return compareFilenames (fullPath, other.fullPath) > 0; }
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
bool File::deleteRecursively() const
|
|
||||||
{
|
|
||||||
bool worked = true;
|
|
||||||
|
|
||||||
if (isDirectory())
|
|
||||||
{
|
|
||||||
Array<File> subFiles;
|
|
||||||
findChildFiles (subFiles, File::findFilesAndDirectories, false);
|
|
||||||
|
|
||||||
for (int i = subFiles.size(); --i >= 0;)
|
|
||||||
worked = subFiles.getReference(i).deleteRecursively() && worked;
|
|
||||||
}
|
|
||||||
|
|
||||||
return deleteFile() && worked;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
String File::getPathUpToLastSlash() const
|
|
||||||
{
|
|
||||||
const int lastSlash = fullPath.lastIndexOfChar (separator);
|
|
||||||
|
|
||||||
if (lastSlash > 0)
|
|
||||||
return fullPath.substring (0, lastSlash);
|
|
||||||
|
|
||||||
if (lastSlash == 0)
|
|
||||||
return separatorString;
|
|
||||||
|
|
||||||
return fullPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
File File::getParentDirectory() const
|
|
||||||
{
|
|
||||||
File f;
|
|
||||||
f.fullPath = getPathUpToLastSlash();
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
String File::getFileName() const
|
|
||||||
{
|
|
||||||
return fullPath.substring (fullPath.lastIndexOfChar (separator) + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
String File::getFileNameWithoutExtension() const
|
|
||||||
{
|
|
||||||
const int lastSlash = fullPath.lastIndexOfChar (separator) + 1;
|
|
||||||
const int lastDot = fullPath.lastIndexOfChar ('.');
|
|
||||||
|
|
||||||
if (lastDot > lastSlash)
|
|
||||||
return fullPath.substring (lastSlash, lastDot);
|
|
||||||
|
|
||||||
return fullPath.substring (lastSlash);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool File::isAChildOf (const File& potentialParent) const
|
|
||||||
{
|
|
||||||
if (potentialParent == File::nonexistent ())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const String ourPath (getPathUpToLastSlash());
|
|
||||||
|
|
||||||
if (compareFilenames (potentialParent.fullPath, ourPath) == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (potentialParent.fullPath.length() >= ourPath.length())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return getParentDirectory().isAChildOf (potentialParent);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
bool File::isAbsolutePath (const String& path)
|
|
||||||
{
|
|
||||||
return path.startsWithChar (separator)
|
|
||||||
#if BEAST_WINDOWS
|
|
||||||
|| (path.isNotEmpty() && path[1] == ':');
|
|
||||||
#else
|
|
||||||
|| path.startsWithChar ('~');
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
File File::getChildFile (String relativePath) const
|
|
||||||
{
|
|
||||||
if (isAbsolutePath (relativePath))
|
|
||||||
return File (relativePath);
|
|
||||||
|
|
||||||
String path (fullPath);
|
|
||||||
|
|
||||||
// It's relative, so remove any ../ or ./ bits at the start..
|
|
||||||
if (relativePath[0] == '.')
|
|
||||||
{
|
|
||||||
#if BEAST_WINDOWS
|
|
||||||
relativePath = relativePath.replaceCharacter ('/', '\\');
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while (relativePath[0] == '.')
|
|
||||||
{
|
|
||||||
const beast_wchar secondChar = relativePath[1];
|
|
||||||
|
|
||||||
if (secondChar == '.')
|
|
||||||
{
|
|
||||||
const beast_wchar thirdChar = relativePath[2];
|
|
||||||
|
|
||||||
if (thirdChar == 0 || thirdChar == separator)
|
|
||||||
{
|
|
||||||
const int lastSlash = path.lastIndexOfChar (separator);
|
|
||||||
if (lastSlash >= 0)
|
|
||||||
path = path.substring (0, lastSlash);
|
|
||||||
|
|
||||||
relativePath = relativePath.substring (3);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (secondChar == separator)
|
|
||||||
{
|
|
||||||
relativePath = relativePath.substring (2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return File (addTrailingSeparator (path) + relativePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
File File::getSiblingFile (const String& fileName) const
|
|
||||||
{
|
|
||||||
return getParentDirectory().getChildFile (fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
Result File::create() const
|
|
||||||
{
|
|
||||||
if (exists())
|
|
||||||
return Result::ok();
|
|
||||||
|
|
||||||
const File parentDir (getParentDirectory());
|
|
||||||
|
|
||||||
if (parentDir == *this)
|
|
||||||
return Result::fail ("Cannot create parent directory");
|
|
||||||
|
|
||||||
Result r (parentDir.createDirectory());
|
|
||||||
|
|
||||||
if (r.wasOk())
|
|
||||||
{
|
|
||||||
FileOutputStream fo (*this, 8);
|
|
||||||
r = fo.getStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result File::createDirectory() const
|
|
||||||
{
|
|
||||||
if (isDirectory())
|
|
||||||
return Result::ok();
|
|
||||||
|
|
||||||
const File parentDir (getParentDirectory());
|
|
||||||
|
|
||||||
if (parentDir == *this)
|
|
||||||
return Result::fail ("Cannot create parent directory");
|
|
||||||
|
|
||||||
Result r (parentDir.createDirectory());
|
|
||||||
|
|
||||||
if (r.wasOk())
|
|
||||||
r = createDirectoryInternal (fullPath.trimCharactersAtEnd (separatorString));
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
int File::findChildFiles (Array<File>& results,
|
|
||||||
const int whatToLookFor,
|
|
||||||
const bool searchRecursively,
|
|
||||||
const String& wildCardPattern) const
|
|
||||||
{
|
|
||||||
DirectoryIterator di (*this, searchRecursively, wildCardPattern, whatToLookFor);
|
|
||||||
|
|
||||||
int total = 0;
|
|
||||||
while (di.next())
|
|
||||||
{
|
|
||||||
results.add (di.getFile());
|
|
||||||
++total;
|
|
||||||
}
|
|
||||||
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
||||||
int File::getNumberOfChildFiles (const int whatToLookFor, const String& wildCardPattern) const
|
|
||||||
{
|
|
||||||
DirectoryIterator di (*this, false, wildCardPattern, whatToLookFor);
|
|
||||||
|
|
||||||
int total = 0;
|
|
||||||
while (di.next())
|
|
||||||
++total;
|
|
||||||
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
String File::getFileExtension() const
|
|
||||||
{
|
|
||||||
const int indexOfDot = fullPath.lastIndexOfChar ('.');
|
|
||||||
|
|
||||||
if (indexOfDot > fullPath.lastIndexOfChar (separator))
|
|
||||||
return fullPath.substring (indexOfDot);
|
|
||||||
|
|
||||||
return String::empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool File::hasFileExtension (const String& possibleSuffix) const
|
|
||||||
{
|
|
||||||
if (possibleSuffix.isEmpty())
|
|
||||||
return fullPath.lastIndexOfChar ('.') <= fullPath.lastIndexOfChar (separator);
|
|
||||||
|
|
||||||
const int semicolon = possibleSuffix.indexOfChar (0, ';');
|
|
||||||
|
|
||||||
if (semicolon >= 0)
|
|
||||||
{
|
|
||||||
return hasFileExtension (possibleSuffix.substring (0, semicolon).trimEnd())
|
|
||||||
|| hasFileExtension (possibleSuffix.substring (semicolon + 1).trimStart());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (fullPath.endsWithIgnoreCase (possibleSuffix))
|
|
||||||
{
|
|
||||||
if (possibleSuffix.startsWithChar ('.'))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
const int dotPos = fullPath.length() - possibleSuffix.length() - 1;
|
|
||||||
|
|
||||||
if (dotPos >= 0)
|
|
||||||
return fullPath [dotPos] == '.';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
File File::withFileExtension (const String& newExtension) const
|
|
||||||
{
|
|
||||||
if (fullPath.isEmpty())
|
|
||||||
return File::nonexistent ();
|
|
||||||
|
|
||||||
String filePart (getFileName());
|
|
||||||
|
|
||||||
const int i = filePart.lastIndexOfChar ('.');
|
|
||||||
if (i >= 0)
|
|
||||||
filePart = filePart.substring (0, i);
|
|
||||||
|
|
||||||
if (newExtension.isNotEmpty() && ! newExtension.startsWithChar ('.'))
|
|
||||||
filePart << '.';
|
|
||||||
|
|
||||||
return getSiblingFile (filePart + newExtension);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
FileInputStream* File::createInputStream() const
|
|
||||||
{
|
|
||||||
std::unique_ptr <FileInputStream> fin (new FileInputStream (*this));
|
|
||||||
|
|
||||||
if (fin->openedOk())
|
|
||||||
return fin.release();
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileOutputStream* File::createOutputStream (const size_t bufferSize) const
|
|
||||||
{
|
|
||||||
std::unique_ptr <FileOutputStream> out (new FileOutputStream (*this, bufferSize));
|
|
||||||
|
|
||||||
return out->failedToOpen() ? nullptr
|
|
||||||
: out.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
bool File::appendData (const void* const dataToAppend,
|
|
||||||
const size_t numberOfBytes) const
|
|
||||||
{
|
|
||||||
bassert (((std::ptrdiff_t) numberOfBytes) >= 0);
|
|
||||||
|
|
||||||
if (numberOfBytes == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
FileOutputStream out (*this, 8192);
|
|
||||||
return out.openedOk() && out.write (dataToAppend, numberOfBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool File::appendText (const String& text,
|
|
||||||
const bool asUnicode,
|
|
||||||
const bool writeUnicodeHeaderBytes) const
|
|
||||||
{
|
|
||||||
FileOutputStream out (*this);
|
|
||||||
|
|
||||||
if (out.failedToOpen())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
out.writeText (text, asUnicode, writeUnicodeHeaderBytes);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
File File::createTempFile (const String& fileNameEnding)
|
|
||||||
{
|
|
||||||
const File tempFile (getSpecialLocation (tempDirectory)
|
|
||||||
.getChildFile ("temp_" + String::toHexString (Random::getSystemRandom().nextInt()))
|
|
||||||
.withFileExtension (fileNameEnding));
|
|
||||||
|
|
||||||
if (tempFile.exists())
|
|
||||||
return createTempFile (fileNameEnding);
|
|
||||||
|
|
||||||
return tempFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
@@ -1,529 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Portions of this file are from JUCE.
|
|
||||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
|
||||||
Please visit http://www.juce.com
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_MODULE_CORE_FILES_FILE_H_INCLUDED
|
|
||||||
#define BEAST_MODULE_CORE_FILES_FILE_H_INCLUDED
|
|
||||||
|
|
||||||
#include <beast/module/core/containers/Array.h>
|
|
||||||
#include <beast/module/core/memory/MemoryBlock.h>
|
|
||||||
#include <beast/module/core/misc/Result.h>
|
|
||||||
#include <beast/module/core/text/StringArray.h>
|
|
||||||
#include <beast/module/core/threads/CriticalSection.h>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
class FileInputStream;
|
|
||||||
class FileOutputStream;
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/**
|
|
||||||
Represents a local file or directory.
|
|
||||||
|
|
||||||
This class encapsulates the absolute pathname of a file or directory, and
|
|
||||||
has methods for finding out about the file and changing its properties.
|
|
||||||
|
|
||||||
To read or write to the file, there are methods for returning an input or
|
|
||||||
output stream.
|
|
||||||
|
|
||||||
@see FileInputStream, FileOutputStream
|
|
||||||
*/
|
|
||||||
class File
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//==============================================================================
|
|
||||||
/** Creates an (invalid) file object.
|
|
||||||
|
|
||||||
The file is initially set to an empty path, so getFullPath() will return
|
|
||||||
an empty string, and comparing the file to File::nonexistent will return
|
|
||||||
true.
|
|
||||||
|
|
||||||
You can use its operator= method to point it at a proper file.
|
|
||||||
*/
|
|
||||||
File() noexcept {}
|
|
||||||
|
|
||||||
/** Creates a file from an absolute path.
|
|
||||||
|
|
||||||
If the path supplied is a relative path, it is taken to be relative
|
|
||||||
to the current working directory (see File::getCurrentWorkingDirectory()),
|
|
||||||
but this isn't a recommended way of creating a file, because you
|
|
||||||
never know what the CWD is going to be.
|
|
||||||
|
|
||||||
On the Mac/Linux, the path can include "~" notation for referring to
|
|
||||||
user home directories.
|
|
||||||
*/
|
|
||||||
File (const String& absolutePath);
|
|
||||||
|
|
||||||
/** Creates a copy of another file object. */
|
|
||||||
File (const File&);
|
|
||||||
|
|
||||||
/** Destructor. */
|
|
||||||
~File() noexcept {}
|
|
||||||
|
|
||||||
/** Sets the file based on an absolute pathname.
|
|
||||||
|
|
||||||
If the path supplied is a relative path, it is taken to be relative
|
|
||||||
to the current working directory (see File::getCurrentWorkingDirectory()),
|
|
||||||
but this isn't a recommended way of creating a file, because you
|
|
||||||
never know what the CWD is going to be.
|
|
||||||
|
|
||||||
On the Mac/Linux, the path can include "~" notation for referring to
|
|
||||||
user home directories.
|
|
||||||
*/
|
|
||||||
File& operator= (const String& newAbsolutePath);
|
|
||||||
|
|
||||||
/** Copies from another file object. */
|
|
||||||
File& operator= (const File& otherFile);
|
|
||||||
|
|
||||||
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
|
||||||
File (File&&) noexcept;
|
|
||||||
File& operator= (File&&) noexcept;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** This static constant is used for referring to an 'invalid' file. */
|
|
||||||
static File const& nonexistent ();
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Checks whether the file actually exists.
|
|
||||||
|
|
||||||
@returns true if the file exists, either as a file or a directory.
|
|
||||||
@see existsAsFile, isDirectory
|
|
||||||
*/
|
|
||||||
bool exists() const;
|
|
||||||
|
|
||||||
/** Checks whether the file exists and is a file rather than a directory.
|
|
||||||
|
|
||||||
@returns true only if this is a real file, false if it's a directory
|
|
||||||
or doesn't exist
|
|
||||||
@see exists, isDirectory
|
|
||||||
*/
|
|
||||||
bool existsAsFile() const;
|
|
||||||
|
|
||||||
/** Checks whether the file is a directory that exists.
|
|
||||||
|
|
||||||
@returns true only if the file is a directory which actually exists, so
|
|
||||||
false if it's a file or doesn't exist at all
|
|
||||||
@see exists, existsAsFile
|
|
||||||
*/
|
|
||||||
bool isDirectory() const;
|
|
||||||
|
|
||||||
/** Returns the size of the file in bytes.
|
|
||||||
|
|
||||||
@returns the number of bytes in the file, or 0 if it doesn't exist.
|
|
||||||
*/
|
|
||||||
std::int64_t getSize() const;
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Returns the complete, absolute path of this file.
|
|
||||||
|
|
||||||
This includes the filename and all its parent folders. On Windows it'll
|
|
||||||
also include the drive letter prefix; on Mac or Linux it'll be a complete
|
|
||||||
path starting from the root folder.
|
|
||||||
|
|
||||||
If you just want the file's name, you should use getFileName() or
|
|
||||||
getFileNameWithoutExtension().
|
|
||||||
|
|
||||||
@see getFileName
|
|
||||||
*/
|
|
||||||
const String& getFullPathName() const noexcept { return fullPath; }
|
|
||||||
|
|
||||||
/** Returns the last section of the pathname.
|
|
||||||
|
|
||||||
Returns just the final part of the path - e.g. if the whole path
|
|
||||||
is "/moose/fish/foo.txt" this will return "foo.txt".
|
|
||||||
|
|
||||||
For a directory, it returns the final part of the path - e.g. for the
|
|
||||||
directory "/moose/fish" it'll return "fish".
|
|
||||||
|
|
||||||
If the filename begins with a dot, it'll return the whole filename, e.g. for
|
|
||||||
"/moose/.fish", it'll return ".fish"
|
|
||||||
|
|
||||||
@see getFullPathName, getFileNameWithoutExtension
|
|
||||||
*/
|
|
||||||
String getFileName() const;
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Returns the file's extension.
|
|
||||||
|
|
||||||
Returns the file extension of this file, also including the dot.
|
|
||||||
|
|
||||||
e.g. "/moose/fish/foo.txt" would return ".txt"
|
|
||||||
|
|
||||||
@see hasFileExtension, withFileExtension, getFileNameWithoutExtension
|
|
||||||
*/
|
|
||||||
String getFileExtension() const;
|
|
||||||
|
|
||||||
/** Checks whether the file has a given extension.
|
|
||||||
|
|
||||||
@param extensionToTest the extension to look for - it doesn't matter whether or
|
|
||||||
not this string has a dot at the start, so ".wav" and "wav"
|
|
||||||
will have the same effect. To compare with multiple extensions, this
|
|
||||||
parameter can contain multiple strings, separated by semi-colons -
|
|
||||||
so, for example: hasFileExtension (".jpeg;png;gif") would return
|
|
||||||
true if the file has any of those three extensions.
|
|
||||||
|
|
||||||
@see getFileExtension, withFileExtension, getFileNameWithoutExtension
|
|
||||||
*/
|
|
||||||
bool hasFileExtension (const String& extensionToTest) const;
|
|
||||||
|
|
||||||
/** Returns a version of this file with a different file extension.
|
|
||||||
|
|
||||||
e.g. File ("/moose/fish/foo.txt").withFileExtension ("html") returns "/moose/fish/foo.html"
|
|
||||||
|
|
||||||
@param newExtension the new extension, either with or without a dot at the start (this
|
|
||||||
doesn't make any difference). To get remove a file's extension altogether,
|
|
||||||
pass an empty string into this function.
|
|
||||||
|
|
||||||
@see getFileName, getFileExtension, hasFileExtension, getFileNameWithoutExtension
|
|
||||||
*/
|
|
||||||
File withFileExtension (const String& newExtension) const;
|
|
||||||
|
|
||||||
/** Returns the last part of the filename, without its file extension.
|
|
||||||
|
|
||||||
e.g. for "/moose/fish/foo.txt" this will return "foo".
|
|
||||||
|
|
||||||
@see getFileName, getFileExtension, hasFileExtension, withFileExtension
|
|
||||||
*/
|
|
||||||
String getFileNameWithoutExtension() const;
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Returns a file that represents a relative (or absolute) sub-path of the current one.
|
|
||||||
|
|
||||||
This will find a child file or directory of the current object.
|
|
||||||
|
|
||||||
e.g.
|
|
||||||
File ("/moose/fish").getChildFile ("foo.txt") will produce "/moose/fish/foo.txt".
|
|
||||||
File ("/moose/fish").getChildFile ("haddock/foo.txt") will produce "/moose/fish/haddock/foo.txt".
|
|
||||||
File ("/moose/fish").getChildFile ("../foo.txt") will produce "/moose/foo.txt".
|
|
||||||
|
|
||||||
If the string is actually an absolute path, it will be treated as such, e.g.
|
|
||||||
File ("/moose/fish").getChildFile ("/foo.txt") will produce "/foo.txt"
|
|
||||||
|
|
||||||
@see getSiblingFile, getParentDirectory, isAChildOf
|
|
||||||
*/
|
|
||||||
File getChildFile (String relativeOrAbsolutePath) const;
|
|
||||||
|
|
||||||
/** Returns a file which is in the same directory as this one.
|
|
||||||
|
|
||||||
This is equivalent to getParentDirectory().getChildFile (name).
|
|
||||||
|
|
||||||
@see getChildFile, getParentDirectory
|
|
||||||
*/
|
|
||||||
File getSiblingFile (const String& siblingFileName) const;
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Returns the directory that contains this file or directory.
|
|
||||||
|
|
||||||
e.g. for "/moose/fish/foo.txt" this will return "/moose/fish".
|
|
||||||
*/
|
|
||||||
File getParentDirectory() const;
|
|
||||||
|
|
||||||
/** Checks whether a file is somewhere inside a directory.
|
|
||||||
|
|
||||||
Returns true if this file is somewhere inside a subdirectory of the directory
|
|
||||||
that is passed in. Neither file actually has to exist, because the function
|
|
||||||
just checks the paths for similarities.
|
|
||||||
|
|
||||||
e.g. File ("/moose/fish/foo.txt").isAChildOf ("/moose") is true.
|
|
||||||
File ("/moose/fish/foo.txt").isAChildOf ("/moose/fish") is also true.
|
|
||||||
*/
|
|
||||||
bool isAChildOf (const File& potentialParentDirectory) const;
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Compares the pathnames for two files. */
|
|
||||||
bool operator== (const File&) const;
|
|
||||||
/** Compares the pathnames for two files. */
|
|
||||||
bool operator!= (const File&) const;
|
|
||||||
/** Compares the pathnames for two files. */
|
|
||||||
bool operator< (const File&) const;
|
|
||||||
/** Compares the pathnames for two files. */
|
|
||||||
bool operator> (const File&) const;
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Creates an empty file if it doesn't already exist.
|
|
||||||
|
|
||||||
If the file that this object refers to doesn't exist, this will create a file
|
|
||||||
of zero size.
|
|
||||||
|
|
||||||
If it already exists or is a directory, this method will do nothing.
|
|
||||||
|
|
||||||
@returns true if the file has been created (or if it already existed).
|
|
||||||
@see createDirectory
|
|
||||||
*/
|
|
||||||
Result create() const;
|
|
||||||
|
|
||||||
/** Creates a new directory for this filename.
|
|
||||||
|
|
||||||
This will try to create the file as a directory, and fill also create
|
|
||||||
any parent directories it needs in order to complete the operation.
|
|
||||||
|
|
||||||
@returns a result to indicate whether the directory was created successfully, or
|
|
||||||
an error message if it failed.
|
|
||||||
@see create
|
|
||||||
*/
|
|
||||||
Result createDirectory() const;
|
|
||||||
|
|
||||||
/** Deletes a file.
|
|
||||||
|
|
||||||
If this file is actually a directory, it may not be deleted correctly if it
|
|
||||||
contains files. See deleteRecursively() as a better way of deleting directories.
|
|
||||||
|
|
||||||
@returns true if the file has been successfully deleted (or if it didn't exist to
|
|
||||||
begin with).
|
|
||||||
@see deleteRecursively
|
|
||||||
*/
|
|
||||||
bool deleteFile() const;
|
|
||||||
|
|
||||||
/** Deletes a file or directory and all its subdirectories.
|
|
||||||
|
|
||||||
If this file is a directory, this will try to delete it and all its subfolders. If
|
|
||||||
it's just a file, it will just try to delete the file.
|
|
||||||
|
|
||||||
@returns true if the file and all its subfolders have been successfully deleted
|
|
||||||
(or if it didn't exist to begin with).
|
|
||||||
@see deleteFile
|
|
||||||
*/
|
|
||||||
bool deleteRecursively() const;
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Used in file searching, to specify whether to return files, directories, or both.
|
|
||||||
*/
|
|
||||||
enum TypesOfFileToFind
|
|
||||||
{
|
|
||||||
findDirectories = 1, /**< Use this flag to indicate that you want to find directories. */
|
|
||||||
findFiles = 2, /**< Use this flag to indicate that you want to find files. */
|
|
||||||
findFilesAndDirectories = 3, /**< Use this flag to indicate that you want to find both files and directories. */
|
|
||||||
ignoreHiddenFiles = 4 /**< Add this flag to avoid returning any hidden files in the results. */
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Searches inside a directory for files matching a wildcard pattern.
|
|
||||||
|
|
||||||
Assuming that this file is a directory, this method will search it
|
|
||||||
for either files or subdirectories whose names match a filename pattern.
|
|
||||||
|
|
||||||
@param results an array to which File objects will be added for the
|
|
||||||
files that the search comes up with
|
|
||||||
@param whatToLookFor a value from the TypesOfFileToFind enum, specifying whether to
|
|
||||||
return files, directories, or both. If the ignoreHiddenFiles flag
|
|
||||||
is also added to this value, hidden files won't be returned
|
|
||||||
@param searchRecursively if true, all subdirectories will be recursed into to do
|
|
||||||
an exhaustive search
|
|
||||||
@param wildCardPattern the filename pattern to search for, e.g. "*.txt"
|
|
||||||
@returns the number of results that have been found
|
|
||||||
|
|
||||||
@see getNumberOfChildFiles, DirectoryIterator
|
|
||||||
*/
|
|
||||||
int findChildFiles (Array<File>& results,
|
|
||||||
int whatToLookFor,
|
|
||||||
bool searchRecursively,
|
|
||||||
const String& wildCardPattern = "*") const;
|
|
||||||
|
|
||||||
/** Searches inside a directory and counts how many files match a wildcard pattern.
|
|
||||||
|
|
||||||
Assuming that this file is a directory, this method will search it
|
|
||||||
for either files or subdirectories whose names match a filename pattern,
|
|
||||||
and will return the number of matches found.
|
|
||||||
|
|
||||||
This isn't a recursive call, and will only search this directory, not
|
|
||||||
its children.
|
|
||||||
|
|
||||||
@param whatToLookFor a value from the TypesOfFileToFind enum, specifying whether to
|
|
||||||
count files, directories, or both. If the ignoreHiddenFiles flag
|
|
||||||
is also added to this value, hidden files won't be counted
|
|
||||||
@param wildCardPattern the filename pattern to search for, e.g. "*.txt"
|
|
||||||
@returns the number of matches found
|
|
||||||
@see findChildFiles, DirectoryIterator
|
|
||||||
*/
|
|
||||||
int getNumberOfChildFiles (int whatToLookFor,
|
|
||||||
const String& wildCardPattern = "*") const;
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Creates a stream to read from this file.
|
|
||||||
|
|
||||||
@returns a stream that will read from this file (initially positioned at the
|
|
||||||
start of the file), or nullptr if the file can't be opened for some reason
|
|
||||||
@see createOutputStream
|
|
||||||
*/
|
|
||||||
FileInputStream* createInputStream() const;
|
|
||||||
|
|
||||||
/** Creates a stream to write to this file.
|
|
||||||
|
|
||||||
If the file exists, the stream that is returned will be positioned ready for
|
|
||||||
writing at the end of the file, so you might want to use deleteFile() first
|
|
||||||
to write to an empty file.
|
|
||||||
|
|
||||||
@returns a stream that will write to this file (initially positioned at the
|
|
||||||
end of the file), or nullptr if the file can't be opened for some reason
|
|
||||||
@see createInputStream, appendData, appendText
|
|
||||||
*/
|
|
||||||
FileOutputStream* createOutputStream (size_t bufferSize = 0x8000) const;
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Appends a block of binary data to the end of the file.
|
|
||||||
|
|
||||||
This will try to write the given buffer to the end of the file.
|
|
||||||
|
|
||||||
@returns false if it can't write to the file for some reason
|
|
||||||
*/
|
|
||||||
bool appendData (const void* dataToAppend,
|
|
||||||
size_t numberOfBytes) const;
|
|
||||||
|
|
||||||
/** Appends a string to the end of the file.
|
|
||||||
|
|
||||||
This will try to append a text string to the file, as either 16-bit unicode
|
|
||||||
or 8-bit characters in the default system encoding.
|
|
||||||
|
|
||||||
It can also write the 'ff fe' unicode header bytes before the text to indicate
|
|
||||||
the endianness of the file.
|
|
||||||
|
|
||||||
Any single \\n characters in the string are replaced with \\r\\n before it is written.
|
|
||||||
|
|
||||||
@see replaceWithText
|
|
||||||
*/
|
|
||||||
bool appendText (const String& textToAppend,
|
|
||||||
bool asUnicode = false,
|
|
||||||
bool writeUnicodeHeaderBytes = false) const;
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** A set of types of location that can be passed to the getSpecialLocation() method.
|
|
||||||
*/
|
|
||||||
enum SpecialLocationType
|
|
||||||
{
|
|
||||||
/** The user's home folder. This is the same as using File ("~"). */
|
|
||||||
userHomeDirectory,
|
|
||||||
|
|
||||||
/** The user's default documents folder. On Windows, this might be the user's
|
|
||||||
"My Documents" folder. On the Mac it'll be their "Documents" folder. Linux
|
|
||||||
doesn't tend to have one of these, so it might just return their home folder.
|
|
||||||
*/
|
|
||||||
userDocumentsDirectory,
|
|
||||||
|
|
||||||
/** The folder that contains the user's desktop objects. */
|
|
||||||
userDesktopDirectory,
|
|
||||||
|
|
||||||
/** The most likely place where a user might store their music files. */
|
|
||||||
userMusicDirectory,
|
|
||||||
|
|
||||||
/** The most likely place where a user might store their movie files. */
|
|
||||||
userMoviesDirectory,
|
|
||||||
|
|
||||||
/** The most likely place where a user might store their picture files. */
|
|
||||||
userPicturesDirectory,
|
|
||||||
|
|
||||||
/** The folder in which applications store their persistent user-specific settings.
|
|
||||||
On Windows, this might be "\Documents and Settings\username\Application Data".
|
|
||||||
On the Mac, it might be "~/Library". If you're going to store your settings in here,
|
|
||||||
always create your own sub-folder to put them in, to avoid making a mess.
|
|
||||||
*/
|
|
||||||
userApplicationDataDirectory,
|
|
||||||
|
|
||||||
/** An equivalent of the userApplicationDataDirectory folder that is shared by all users
|
|
||||||
of the computer, rather than just the current user.
|
|
||||||
|
|
||||||
On the Mac it'll be "/Library", on Windows, it could be something like
|
|
||||||
"\Documents and Settings\All Users\Application Data".
|
|
||||||
|
|
||||||
Depending on the setup, this folder may be read-only.
|
|
||||||
*/
|
|
||||||
commonApplicationDataDirectory,
|
|
||||||
|
|
||||||
/** A place to put documents which are shared by all users of the machine.
|
|
||||||
On Windows this may be somewhere like "C:\Users\Public\Documents", on OSX it
|
|
||||||
will be something like "/Users/Shared". Other OSes may have no such concept
|
|
||||||
though, so be careful.
|
|
||||||
*/
|
|
||||||
commonDocumentsDirectory,
|
|
||||||
|
|
||||||
/** The folder that should be used for temporary files.
|
|
||||||
Always delete them when you're finished, to keep the user's computer tidy!
|
|
||||||
*/
|
|
||||||
tempDirectory,
|
|
||||||
|
|
||||||
/** The directory in which applications normally get installed.
|
|
||||||
So on windows, this would be something like "c:\program files", on the
|
|
||||||
Mac "/Applications", or "/usr" on linux.
|
|
||||||
*/
|
|
||||||
globalApplicationsDirectory
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Finds the location of a special type of file or directory, such as a home folder or
|
|
||||||
documents folder.
|
|
||||||
|
|
||||||
@see SpecialLocationType
|
|
||||||
*/
|
|
||||||
static File getSpecialLocation (const SpecialLocationType type);
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Returns a temporary file in the system's temp directory.
|
|
||||||
This will try to return the name of a non-existent temp file.
|
|
||||||
To get the temp folder, you can use getSpecialLocation (File::tempDirectory).
|
|
||||||
*/
|
|
||||||
static File createTempFile (const String& fileNameEnding);
|
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Returns the current working directory. */
|
|
||||||
static File getCurrentWorkingDirectory();
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** The system-specific file separator character.
|
|
||||||
On Windows, this will be '\', on Mac/Linux, it'll be '/'
|
|
||||||
*/
|
|
||||||
static const beast_wchar separator;
|
|
||||||
|
|
||||||
/** The system-specific file separator character, as a string.
|
|
||||||
On Windows, this will be '\', on Mac/Linux, it'll be '/'
|
|
||||||
*/
|
|
||||||
static const String separatorString;
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Indicates whether filenames are case-sensitive on the current operating system. */
|
|
||||||
static bool areFileNamesCaseSensitive();
|
|
||||||
|
|
||||||
/** Returns true if the string seems to be a fully-specified absolute path. */
|
|
||||||
static bool isAbsolutePath (const String& path);
|
|
||||||
|
|
||||||
/** Creates a file that simply contains this string, without doing the sanity-checking
|
|
||||||
that the normal constructors do.
|
|
||||||
|
|
||||||
Best to avoid this unless you really know what you're doing.
|
|
||||||
*/
|
|
||||||
static File createFileWithoutCheckingPath (const String& absolutePath) noexcept;
|
|
||||||
|
|
||||||
/** Adds a separator character to the end of a path if it doesn't already have one. */
|
|
||||||
static String addTrailingSeparator (const String& path);
|
|
||||||
|
|
||||||
private:
|
|
||||||
//==============================================================================
|
|
||||||
String fullPath;
|
|
||||||
|
|
||||||
static String parseAbsolutePath (const String&);
|
|
||||||
String getPathUpToLastSlash() const;
|
|
||||||
|
|
||||||
Result createDirectoryInternal (const String&) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Portions of this file are from JUCE.
|
|
||||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
|
||||||
Please visit http://www.juce.com
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
namespace beast
|
|
||||||
{
|
|
||||||
|
|
||||||
std::int64_t beast_fileSetPosition (void* handle, std::int64_t pos);
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
FileInputStream::FileInputStream (const File& f)
|
|
||||||
: file (f),
|
|
||||||
fileHandle (nullptr),
|
|
||||||
currentPosition (0),
|
|
||||||
status (Result::ok()),
|
|
||||||
needToSeek (true)
|
|
||||||
{
|
|
||||||
openHandle();
|
|
||||||
}
|
|
||||||
|
|
||||||
FileInputStream::~FileInputStream()
|
|
||||||
{
|
|
||||||
closeHandle();
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
std::int64_t FileInputStream::getTotalLength()
|
|
||||||
{
|
|
||||||
return file.getSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
int FileInputStream::read (void* buffer, int bytesToRead)
|
|
||||||
{
|
|
||||||
bassert (openedOk());
|
|
||||||
bassert (buffer != nullptr && bytesToRead >= 0);
|
|
||||||
|
|
||||||
if (needToSeek)
|
|
||||||
{
|
|
||||||
if (beast_fileSetPosition (fileHandle, currentPosition) < 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
needToSeek = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const size_t num = readInternal (buffer, (size_t) bytesToRead);
|
|
||||||
currentPosition += num;
|
|
||||||
|
|
||||||
return (int) num;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileInputStream::isExhausted()
|
|
||||||
{
|
|
||||||
return currentPosition >= getTotalLength();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::int64_t FileInputStream::getPosition()
|
|
||||||
{
|
|
||||||
return currentPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileInputStream::setPosition (std::int64_t pos)
|
|
||||||
{
|
|
||||||
bassert (openedOk());
|
|
||||||
|
|
||||||
if (pos != currentPosition)
|
|
||||||
{
|
|
||||||
pos = blimit ((std::int64_t) 0, getTotalLength(), pos);
|
|
||||||
|
|
||||||
needToSeek |= (currentPosition != pos);
|
|
||||||
currentPosition = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Portions of this file are from JUCE.
|
|
||||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
|
||||||
Please visit http://www.juce.com
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_MODULE_CORE_FILES_FILEINPUTSTREAM_H_INCLUDED
|
|
||||||
#define BEAST_MODULE_CORE_FILES_FILEINPUTSTREAM_H_INCLUDED
|
|
||||||
|
|
||||||
namespace beast
|
|
||||||
{
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/**
|
|
||||||
An input stream that reads from a local file.
|
|
||||||
|
|
||||||
@see InputStream, FileOutputStream, File::createInputStream
|
|
||||||
*/
|
|
||||||
class FileInputStream
|
|
||||||
: public InputStream
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//==============================================================================
|
|
||||||
/** Creates a FileInputStream.
|
|
||||||
|
|
||||||
@param fileToRead the file to read from - if the file can't be accessed for some
|
|
||||||
reason, then the stream will just contain no data
|
|
||||||
*/
|
|
||||||
explicit FileInputStream (const File& fileToRead);
|
|
||||||
|
|
||||||
/** Destructor. */
|
|
||||||
~FileInputStream();
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Returns the file that this stream is reading from. */
|
|
||||||
const File& getFile() const noexcept { return file; }
|
|
||||||
|
|
||||||
/** Returns the status of the file stream.
|
|
||||||
The result will be ok if the file opened successfully. If an error occurs while
|
|
||||||
opening or reading from the file, this will contain an error message.
|
|
||||||
*/
|
|
||||||
const Result& getStatus() const noexcept { return status; }
|
|
||||||
|
|
||||||
/** Returns true if the stream couldn't be opened for some reason.
|
|
||||||
@see getResult()
|
|
||||||
*/
|
|
||||||
bool failedToOpen() const noexcept { return status.failed(); }
|
|
||||||
|
|
||||||
/** Returns true if the stream opened without problems.
|
|
||||||
@see getResult()
|
|
||||||
*/
|
|
||||||
bool openedOk() const noexcept { return status.wasOk(); }
|
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
std::int64_t getTotalLength();
|
|
||||||
int read (void* destBuffer, int maxBytesToRead);
|
|
||||||
bool isExhausted();
|
|
||||||
std::int64_t getPosition();
|
|
||||||
bool setPosition (std::int64_t pos);
|
|
||||||
|
|
||||||
private:
|
|
||||||
//==============================================================================
|
|
||||||
File file;
|
|
||||||
void* fileHandle;
|
|
||||||
std::int64_t currentPosition;
|
|
||||||
Result status;
|
|
||||||
bool needToSeek;
|
|
||||||
|
|
||||||
void openHandle();
|
|
||||||
void closeHandle();
|
|
||||||
size_t readInternal (void* buffer, size_t numBytes);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
#endif // BEAST_FILEINPUTSTREAM_H_INCLUDED
|
|
||||||
@@ -1,137 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Portions of this file are from JUCE.
|
|
||||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
|
||||||
Please visit http://www.juce.com
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace beast
|
|
||||||
{
|
|
||||||
|
|
||||||
std::int64_t beast_fileSetPosition (void* handle, std::int64_t pos);
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
FileOutputStream::FileOutputStream (const File& f, const size_t bufferSizeToUse)
|
|
||||||
: file (f),
|
|
||||||
fileHandle (nullptr),
|
|
||||||
status (Result::ok()),
|
|
||||||
currentPosition (0),
|
|
||||||
bufferSize (bufferSizeToUse),
|
|
||||||
bytesInBuffer (0),
|
|
||||||
buffer (std::max (bufferSizeToUse, (size_t) 16))
|
|
||||||
{
|
|
||||||
openHandle();
|
|
||||||
}
|
|
||||||
|
|
||||||
FileOutputStream::~FileOutputStream()
|
|
||||||
{
|
|
||||||
flushBuffer();
|
|
||||||
flushInternal();
|
|
||||||
closeHandle();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::int64_t FileOutputStream::getPosition()
|
|
||||||
{
|
|
||||||
return currentPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileOutputStream::setPosition (std::int64_t newPosition)
|
|
||||||
{
|
|
||||||
if (newPosition != currentPosition)
|
|
||||||
{
|
|
||||||
flushBuffer();
|
|
||||||
currentPosition = beast_fileSetPosition (fileHandle, newPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
return newPosition == currentPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileOutputStream::flushBuffer()
|
|
||||||
{
|
|
||||||
bool ok = true;
|
|
||||||
|
|
||||||
if (bytesInBuffer > 0)
|
|
||||||
{
|
|
||||||
ok = (writeInternal (buffer, bytesInBuffer) == (std::ptrdiff_t) bytesInBuffer);
|
|
||||||
bytesInBuffer = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileOutputStream::flush()
|
|
||||||
{
|
|
||||||
flushBuffer();
|
|
||||||
flushInternal();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileOutputStream::write (const void* const src, const size_t numBytes)
|
|
||||||
{
|
|
||||||
bassert (src != nullptr && ((std::ptrdiff_t) numBytes) >= 0);
|
|
||||||
|
|
||||||
if (bytesInBuffer + numBytes < bufferSize)
|
|
||||||
{
|
|
||||||
memcpy (buffer + bytesInBuffer, src, numBytes);
|
|
||||||
bytesInBuffer += numBytes;
|
|
||||||
currentPosition += numBytes;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (! flushBuffer())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (numBytes < bufferSize)
|
|
||||||
{
|
|
||||||
memcpy (buffer + bytesInBuffer, src, numBytes);
|
|
||||||
bytesInBuffer += numBytes;
|
|
||||||
currentPosition += numBytes;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const std::ptrdiff_t bytesWritten = writeInternal (src, numBytes);
|
|
||||||
|
|
||||||
if (bytesWritten < 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
currentPosition += bytesWritten;
|
|
||||||
return bytesWritten == (std::ptrdiff_t) numBytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FileOutputStream::writeRepeatedByte (std::uint8_t byte, size_t numBytes)
|
|
||||||
{
|
|
||||||
bassert (((std::ptrdiff_t) numBytes) >= 0);
|
|
||||||
|
|
||||||
if (bytesInBuffer + numBytes < bufferSize)
|
|
||||||
{
|
|
||||||
memset (buffer + bytesInBuffer, byte, numBytes);
|
|
||||||
bytesInBuffer += numBytes;
|
|
||||||
currentPosition += numBytes;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return OutputStream::writeRepeatedByte (byte, numBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Portions of this file are from JUCE.
|
|
||||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
|
||||||
Please visit http://www.juce.com
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
namespace beast
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifndef BEAST_MODULE_CORE_FILES_FILEOUTPUTSTREAM_H_INCLUDED
|
|
||||||
#define BEAST_MODULE_CORE_FILES_FILEOUTPUTSTREAM_H_INCLUDED
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/**
|
|
||||||
An output stream that writes into a local file.
|
|
||||||
|
|
||||||
@see OutputStream, FileInputStream, File::createOutputStream
|
|
||||||
*/
|
|
||||||
class FileOutputStream
|
|
||||||
: public OutputStream
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//==============================================================================
|
|
||||||
/** Creates a FileOutputStream.
|
|
||||||
|
|
||||||
If the file doesn't exist, it will first be created. If the file can't be
|
|
||||||
created or opened, the failedToOpen() method will return
|
|
||||||
true.
|
|
||||||
|
|
||||||
If the file already exists when opened, the stream's write-postion will
|
|
||||||
be set to the end of the file. To overwrite an existing file,
|
|
||||||
use File::deleteFile() before opening the stream, or use setPosition(0)
|
|
||||||
after it's opened (although this won't truncate the file).
|
|
||||||
*/
|
|
||||||
FileOutputStream (const File& fileToWriteTo,
|
|
||||||
size_t bufferSizeToUse = 16384);
|
|
||||||
|
|
||||||
/** Destructor. */
|
|
||||||
~FileOutputStream();
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Returns the file that this stream is writing to.
|
|
||||||
*/
|
|
||||||
const File& getFile() const { return file; }
|
|
||||||
|
|
||||||
/** Returns the status of the file stream.
|
|
||||||
The result will be ok if the file opened successfully. If an error occurs while
|
|
||||||
opening or writing to the file, this will contain an error message.
|
|
||||||
*/
|
|
||||||
const Result& getStatus() const noexcept { return status; }
|
|
||||||
|
|
||||||
/** Returns true if the stream couldn't be opened for some reason.
|
|
||||||
@see getResult()
|
|
||||||
*/
|
|
||||||
bool failedToOpen() const noexcept { return status.failed(); }
|
|
||||||
|
|
||||||
/** Returns true if the stream opened without problems.
|
|
||||||
@see getResult()
|
|
||||||
*/
|
|
||||||
bool openedOk() const noexcept { return status.wasOk(); }
|
|
||||||
|
|
||||||
/** Attempts to truncate the file to the current write position.
|
|
||||||
To truncate a file to a specific size, first use setPosition() to seek to the
|
|
||||||
appropriate location, and then call this method.
|
|
||||||
*/
|
|
||||||
Result truncate();
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
void flush() override;
|
|
||||||
std::int64_t getPosition() override;
|
|
||||||
bool setPosition (std::int64_t) override;
|
|
||||||
bool write (const void*, size_t) override;
|
|
||||||
bool writeRepeatedByte (std::uint8_t byte, size_t numTimesToRepeat) override;
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
//==============================================================================
|
|
||||||
File file;
|
|
||||||
void* fileHandle;
|
|
||||||
Result status;
|
|
||||||
std::int64_t currentPosition;
|
|
||||||
size_t bufferSize, bytesInBuffer;
|
|
||||||
HeapBlock <char> buffer;
|
|
||||||
|
|
||||||
void openHandle();
|
|
||||||
void closeHandle();
|
|
||||||
void flushInternal();
|
|
||||||
bool flushBuffer();
|
|
||||||
std::int64_t setPositionInternal (std::int64_t);
|
|
||||||
std::ptrdiff_t writeInternal (const void*, size_t);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -24,8 +24,6 @@
|
|||||||
#ifndef BEAST_MODULE_CORE_LOGGING_LOGGER_H_INCLUDED
|
#ifndef BEAST_MODULE_CORE_LOGGING_LOGGER_H_INCLUDED
|
||||||
#define BEAST_MODULE_CORE_LOGGING_LOGGER_H_INCLUDED
|
#define BEAST_MODULE_CORE_LOGGING_LOGGER_H_INCLUDED
|
||||||
|
|
||||||
#include <beast/strings/String.h>
|
|
||||||
|
|
||||||
namespace beast
|
namespace beast
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -1,152 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Portions of this file are from JUCE.
|
|
||||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
|
||||||
Please visit http://www.juce.com
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#include <beast/unit_test/suite.h>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
Random::Random (const std::int64_t seedValue) noexcept
|
|
||||||
: seed (seedValue)
|
|
||||||
{
|
|
||||||
nextInt (); // fixes a bug where the first int is always 0
|
|
||||||
}
|
|
||||||
|
|
||||||
Random::Random()
|
|
||||||
: seed (1)
|
|
||||||
{
|
|
||||||
setSeedRandomly();
|
|
||||||
}
|
|
||||||
|
|
||||||
Random::~Random() noexcept
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Random::setSeed (const std::int64_t newSeed) noexcept
|
|
||||||
{
|
|
||||||
seed = newSeed;
|
|
||||||
|
|
||||||
nextInt (); // fixes a bug where the first int is always 0
|
|
||||||
}
|
|
||||||
|
|
||||||
void Random::combineSeed (const std::int64_t seedValue) noexcept
|
|
||||||
{
|
|
||||||
seed ^= nextInt64() ^ seedValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Random::setSeedRandomly()
|
|
||||||
{
|
|
||||||
static std::int64_t globalSeed = 0;
|
|
||||||
|
|
||||||
combineSeed (globalSeed ^ (std::int64_t) (std::intptr_t) this);
|
|
||||||
combineSeed (Time::currentTimeMillis());
|
|
||||||
globalSeed ^= seed;
|
|
||||||
|
|
||||||
nextInt (); // fixes a bug where the first int is always 0
|
|
||||||
}
|
|
||||||
|
|
||||||
Random& Random::getSystemRandom() noexcept
|
|
||||||
{
|
|
||||||
static Random sysRand;
|
|
||||||
return sysRand;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
int Random::nextInt() noexcept
|
|
||||||
{
|
|
||||||
seed = (seed * 0x5deece66dLL + 11) & 0xffffffffffffULL;
|
|
||||||
|
|
||||||
return (int) (seed >> 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Random::nextInt (const int maxValue) noexcept
|
|
||||||
{
|
|
||||||
bassert (maxValue > 0);
|
|
||||||
return (int) ((((unsigned int) nextInt()) * (std::uint64_t) maxValue) >> 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::int64_t Random::nextInt64() noexcept
|
|
||||||
{
|
|
||||||
return (((std::int64_t) nextInt()) << 32) | (std::int64_t) (std::uint64_t) (std::uint32_t) nextInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Random::nextBool() noexcept
|
|
||||||
{
|
|
||||||
return (nextInt() & 0x40000000) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
float Random::nextFloat() noexcept
|
|
||||||
{
|
|
||||||
return static_cast <std::uint32_t> (nextInt()) / (float) 0xffffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
double Random::nextDouble() noexcept
|
|
||||||
{
|
|
||||||
return static_cast <std::uint32_t> (nextInt()) / (double) 0xffffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Random::fillBitsRandomly (void* const buffer, size_t bytes)
|
|
||||||
{
|
|
||||||
int* d = static_cast<int*> (buffer);
|
|
||||||
|
|
||||||
for (; bytes >= sizeof (int); bytes -= sizeof (int))
|
|
||||||
*d++ = nextInt();
|
|
||||||
|
|
||||||
if (bytes > 0)
|
|
||||||
{
|
|
||||||
const int lastBytes = nextInt();
|
|
||||||
memcpy (d, &lastBytes, bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
class Random_test : public unit_test::suite
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void run()
|
|
||||||
{
|
|
||||||
for (int j = 10; --j >= 0;)
|
|
||||||
{
|
|
||||||
Random r;
|
|
||||||
r.setSeedRandomly();
|
|
||||||
|
|
||||||
for (int i = 20; --i >= 0;)
|
|
||||||
{
|
|
||||||
expect (r.nextDouble() >= 0.0 && r.nextDouble() < 1.0);
|
|
||||||
expect (r.nextFloat() >= 0.0f && r.nextFloat() < 1.0f);
|
|
||||||
expect (r.nextInt (5) >= 0 && r.nextInt (5) < 5);
|
|
||||||
expect (r.nextInt (1) == 0);
|
|
||||||
|
|
||||||
int n = r.nextInt (50) + 1;
|
|
||||||
expect (r.nextInt (n) >= 0 && r.nextInt (n) < n);
|
|
||||||
|
|
||||||
n = r.nextInt (0x7ffffffe) + 1;
|
|
||||||
expect (r.nextInt (n) >= 0 && r.nextInt (n) < n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
BEAST_DEFINE_TESTSUITE(Random,beast_core,beast);
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
@@ -1,130 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Portions of this file are from JUCE.
|
|
||||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
|
||||||
Please visit http://www.juce.com
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_MODULE_CORE_MATHS_RANDOM_H_INCLUDED
|
|
||||||
#define BEAST_MODULE_CORE_MATHS_RANDOM_H_INCLUDED
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/**
|
|
||||||
A random number generator.
|
|
||||||
|
|
||||||
You can create a Random object and use it to generate a sequence of random numbers.
|
|
||||||
*/
|
|
||||||
class Random
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//==============================================================================
|
|
||||||
/** Creates a Random object based on a seed value.
|
|
||||||
|
|
||||||
For a given seed value, the subsequent numbers generated by this object
|
|
||||||
will be predictable, so a good idea is to set this value based
|
|
||||||
on the time, e.g.
|
|
||||||
|
|
||||||
new Random (Time::currentTimeMillis())
|
|
||||||
*/
|
|
||||||
explicit Random (std::int64_t seedValue) noexcept;
|
|
||||||
|
|
||||||
/** Creates a Random object using a random seed value.
|
|
||||||
Internally, this calls setSeedRandomly() to randomise the seed.
|
|
||||||
*/
|
|
||||||
Random();
|
|
||||||
|
|
||||||
/** Destructor. */
|
|
||||||
~Random() noexcept;
|
|
||||||
|
|
||||||
/** Returns the next random 32 bit integer.
|
|
||||||
|
|
||||||
@returns a random integer from the full range 0x80000000 to 0x7fffffff
|
|
||||||
*/
|
|
||||||
int nextInt() noexcept;
|
|
||||||
|
|
||||||
/** Returns the next random number, limited to a given range.
|
|
||||||
The maxValue parameter may not be negative, or zero.
|
|
||||||
@returns a random integer between 0 (inclusive) and maxValue (exclusive).
|
|
||||||
*/
|
|
||||||
int nextInt (int maxValue) noexcept;
|
|
||||||
|
|
||||||
/** Returns the next 64-bit random number.
|
|
||||||
|
|
||||||
@returns a random integer from the full range 0x8000000000000000 to 0x7fffffffffffffff
|
|
||||||
*/
|
|
||||||
std::int64_t nextInt64() noexcept;
|
|
||||||
|
|
||||||
/** Returns the next random floating-point number.
|
|
||||||
|
|
||||||
@returns a random value in the range 0 to 1.0
|
|
||||||
*/
|
|
||||||
float nextFloat() noexcept;
|
|
||||||
|
|
||||||
/** Returns the next random floating-point number.
|
|
||||||
|
|
||||||
@returns a random value in the range 0 to 1.0
|
|
||||||
*/
|
|
||||||
double nextDouble() noexcept;
|
|
||||||
|
|
||||||
/** Returns the next random boolean value.
|
|
||||||
*/
|
|
||||||
bool nextBool() noexcept;
|
|
||||||
|
|
||||||
/** Fills a block of memory with random values. */
|
|
||||||
void fillBitsRandomly (void* bufferToFill, size_t sizeInBytes);
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Resets this Random object to a given seed value. */
|
|
||||||
void setSeed (std::int64_t newSeed) noexcept;
|
|
||||||
|
|
||||||
/** Merges this object's seed with another value.
|
|
||||||
This sets the seed to be a value created by combining the current seed and this
|
|
||||||
new value.
|
|
||||||
*/
|
|
||||||
void combineSeed (std::int64_t seedValue) noexcept;
|
|
||||||
|
|
||||||
/** Reseeds this generator using a value generated from various semi-random system
|
|
||||||
properties like the current time, etc.
|
|
||||||
|
|
||||||
Because this function convolves the time with the last seed value, calling
|
|
||||||
it repeatedly will increase the randomness of the final result.
|
|
||||||
*/
|
|
||||||
void setSeedRandomly();
|
|
||||||
|
|
||||||
/** The overhead of creating a new Random object is fairly small, but if you want to avoid
|
|
||||||
it, you can call this method to get a global shared Random object.
|
|
||||||
|
|
||||||
It's not thread-safe though, so threads should use their own Random object, otherwise
|
|
||||||
you run the risk of your random numbers becoming.. erm.. randomly corrupted..
|
|
||||||
*/
|
|
||||||
static Random& getSystemRandom() noexcept;
|
|
||||||
|
|
||||||
private:
|
|
||||||
//==============================================================================
|
|
||||||
std::int64_t seed;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
#endif // BEAST_RANDOM_H_INCLUDED
|
|
||||||
@@ -1,412 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Portions of this file are from JUCE.
|
|
||||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
|
||||||
Please visit http://www.juce.com
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace beast
|
|
||||||
{
|
|
||||||
|
|
||||||
MemoryBlock::MemoryBlock() noexcept
|
|
||||||
: size (0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryBlock::MemoryBlock (const size_t initialSize, const bool initialiseToZero)
|
|
||||||
{
|
|
||||||
if (initialSize > 0)
|
|
||||||
{
|
|
||||||
size = initialSize;
|
|
||||||
data.allocate (initialSize, initialiseToZero);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
size = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryBlock::MemoryBlock (const MemoryBlock& other)
|
|
||||||
: size (other.size)
|
|
||||||
{
|
|
||||||
if (size > 0)
|
|
||||||
{
|
|
||||||
bassert (other.data != nullptr);
|
|
||||||
data.malloc (size);
|
|
||||||
memcpy (data, other.data, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryBlock::MemoryBlock (const void* const dataToInitialiseFrom, const size_t sizeInBytes)
|
|
||||||
: size (sizeInBytes)
|
|
||||||
{
|
|
||||||
bassert (((std::ptrdiff_t) sizeInBytes) >= 0);
|
|
||||||
|
|
||||||
if (size > 0)
|
|
||||||
{
|
|
||||||
bassert (dataToInitialiseFrom != nullptr); // non-zero size, but a zero pointer passed-in?
|
|
||||||
|
|
||||||
data.malloc (size);
|
|
||||||
|
|
||||||
if (dataToInitialiseFrom != nullptr)
|
|
||||||
memcpy (data, dataToInitialiseFrom, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryBlock::~MemoryBlock() noexcept
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryBlock& MemoryBlock::operator= (const MemoryBlock& other)
|
|
||||||
{
|
|
||||||
if (this != &other)
|
|
||||||
{
|
|
||||||
setSize (other.size, false);
|
|
||||||
memcpy (data, other.data, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
|
||||||
MemoryBlock::MemoryBlock (MemoryBlock&& other) noexcept
|
|
||||||
: data (static_cast <HeapBlock <char>&&> (other.data)),
|
|
||||||
size (other.size)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryBlock& MemoryBlock::operator= (MemoryBlock&& other) noexcept
|
|
||||||
{
|
|
||||||
data = static_cast <HeapBlock <char>&&> (other.data);
|
|
||||||
size = other.size;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
bool MemoryBlock::operator== (const MemoryBlock& other) const noexcept
|
|
||||||
{
|
|
||||||
return matches (other.data, other.size);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MemoryBlock::operator!= (const MemoryBlock& other) const noexcept
|
|
||||||
{
|
|
||||||
return ! operator== (other);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MemoryBlock::matches (const void* dataToCompare, size_t dataSize) const noexcept
|
|
||||||
{
|
|
||||||
return size == dataSize
|
|
||||||
&& memcmp (data, dataToCompare, size) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
// this will resize the block to this size
|
|
||||||
void MemoryBlock::setSize (const size_t newSize, const bool initialiseToZero)
|
|
||||||
{
|
|
||||||
if (size != newSize)
|
|
||||||
{
|
|
||||||
if (newSize <= 0)
|
|
||||||
{
|
|
||||||
data.free_up();
|
|
||||||
size = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (data != nullptr)
|
|
||||||
{
|
|
||||||
data.reallocate (newSize);
|
|
||||||
|
|
||||||
if (initialiseToZero && (newSize > size))
|
|
||||||
zeromem (data + size, newSize - size);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
data.allocate (newSize, initialiseToZero);
|
|
||||||
}
|
|
||||||
|
|
||||||
size = newSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryBlock::ensureSize (const size_t minimumSize, const bool initialiseToZero)
|
|
||||||
{
|
|
||||||
if (size < minimumSize)
|
|
||||||
setSize (minimumSize, initialiseToZero);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryBlock::swapWith (MemoryBlock& other) noexcept
|
|
||||||
{
|
|
||||||
std::swap (size, other.size);
|
|
||||||
data.swapWith (other.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
void MemoryBlock::fillWith (const std::uint8_t value) noexcept
|
|
||||||
{
|
|
||||||
memset (data, (int) value, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryBlock::append (const void* const srcData, const size_t numBytes)
|
|
||||||
{
|
|
||||||
if (numBytes > 0)
|
|
||||||
{
|
|
||||||
bassert (srcData != nullptr); // this must not be null!
|
|
||||||
const size_t oldSize = size;
|
|
||||||
setSize (size + numBytes);
|
|
||||||
memcpy (data + oldSize, srcData, numBytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryBlock::replaceWith (const void* const srcData, const size_t numBytes)
|
|
||||||
{
|
|
||||||
if (numBytes > 0)
|
|
||||||
{
|
|
||||||
bassert (srcData != nullptr); // this must not be null!
|
|
||||||
setSize (numBytes);
|
|
||||||
memcpy (data, srcData, numBytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryBlock::insert (const void* const srcData, const size_t numBytes, size_t insertPosition)
|
|
||||||
{
|
|
||||||
if (numBytes > 0)
|
|
||||||
{
|
|
||||||
bassert (srcData != nullptr); // this must not be null!
|
|
||||||
insertPosition = std::min (size, insertPosition);
|
|
||||||
const size_t trailingDataSize = size - insertPosition;
|
|
||||||
setSize (size + numBytes, false);
|
|
||||||
|
|
||||||
if (trailingDataSize > 0)
|
|
||||||
memmove (data + insertPosition + numBytes,
|
|
||||||
data + insertPosition,
|
|
||||||
trailingDataSize);
|
|
||||||
|
|
||||||
memcpy (data + insertPosition, srcData, numBytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryBlock::removeSection (const size_t startByte, const size_t numBytesToRemove)
|
|
||||||
{
|
|
||||||
if (startByte + numBytesToRemove >= size)
|
|
||||||
{
|
|
||||||
setSize (startByte);
|
|
||||||
}
|
|
||||||
else if (numBytesToRemove > 0)
|
|
||||||
{
|
|
||||||
memmove (data + startByte,
|
|
||||||
data + startByte + numBytesToRemove,
|
|
||||||
size - (startByte + numBytesToRemove));
|
|
||||||
|
|
||||||
setSize (size - numBytesToRemove);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryBlock::copyFrom (const void* const src, int offset, size_t num) noexcept
|
|
||||||
{
|
|
||||||
const char* d = static_cast<const char*> (src);
|
|
||||||
|
|
||||||
if (offset < 0)
|
|
||||||
{
|
|
||||||
d -= offset;
|
|
||||||
num += (size_t) -offset;
|
|
||||||
offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((size_t) offset + num > size)
|
|
||||||
num = size - (size_t) offset;
|
|
||||||
|
|
||||||
if (num > 0)
|
|
||||||
memcpy (data + offset, d, num);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryBlock::copyTo (void* const dst, int offset, size_t num) const noexcept
|
|
||||||
{
|
|
||||||
char* d = static_cast<char*> (dst);
|
|
||||||
|
|
||||||
if (offset < 0)
|
|
||||||
{
|
|
||||||
zeromem (d, (size_t) -offset);
|
|
||||||
d -= offset;
|
|
||||||
num -= (size_t) -offset;
|
|
||||||
offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((size_t) offset + num > size)
|
|
||||||
{
|
|
||||||
const size_t newNum = size - (size_t) offset;
|
|
||||||
zeromem (d + newNum, num - newNum);
|
|
||||||
num = newNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (num > 0)
|
|
||||||
memcpy (d, data + offset, num);
|
|
||||||
}
|
|
||||||
|
|
||||||
String MemoryBlock::toString() const
|
|
||||||
{
|
|
||||||
return String (CharPointer_UTF8 (data), size);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
int MemoryBlock::getBitRange (const size_t bitRangeStart, size_t numBits) const noexcept
|
|
||||||
{
|
|
||||||
int res = 0;
|
|
||||||
|
|
||||||
size_t byte = bitRangeStart >> 3;
|
|
||||||
size_t offsetInByte = bitRangeStart & 7;
|
|
||||||
size_t bitsSoFar = 0;
|
|
||||||
|
|
||||||
while (numBits > 0 && (size_t) byte < size)
|
|
||||||
{
|
|
||||||
const size_t bitsThisTime = std::min (numBits, 8 - offsetInByte);
|
|
||||||
const int mask = (0xff >> (8 - bitsThisTime)) << offsetInByte;
|
|
||||||
|
|
||||||
res |= (((data[byte] & mask) >> offsetInByte) << bitsSoFar);
|
|
||||||
|
|
||||||
bitsSoFar += bitsThisTime;
|
|
||||||
numBits -= bitsThisTime;
|
|
||||||
++byte;
|
|
||||||
offsetInByte = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemoryBlock::setBitRange (const size_t bitRangeStart, size_t numBits, int bitsToSet) noexcept
|
|
||||||
{
|
|
||||||
size_t byte = bitRangeStart >> 3;
|
|
||||||
size_t offsetInByte = bitRangeStart & 7;
|
|
||||||
std::uint32_t mask = ~((((std::uint32_t) 0xffffffff) << (32 - numBits)) >> (32 - numBits));
|
|
||||||
|
|
||||||
while (numBits > 0 && (size_t) byte < size)
|
|
||||||
{
|
|
||||||
const size_t bitsThisTime = std::min (numBits, 8 - offsetInByte);
|
|
||||||
|
|
||||||
const std::uint32_t tempMask = (mask << offsetInByte) | ~((((std::uint32_t) 0xffffffff) >> offsetInByte) << offsetInByte);
|
|
||||||
const std::uint32_t tempBits = (std::uint32_t) bitsToSet << offsetInByte;
|
|
||||||
|
|
||||||
data[byte] = (char) (((std::uint32_t) data[byte] & tempMask) | tempBits);
|
|
||||||
|
|
||||||
++byte;
|
|
||||||
numBits -= bitsThisTime;
|
|
||||||
bitsToSet >>= bitsThisTime;
|
|
||||||
mask >>= bitsThisTime;
|
|
||||||
offsetInByte = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
void MemoryBlock::loadFromHexString (const String& hex)
|
|
||||||
{
|
|
||||||
ensureSize ((size_t) hex.length() >> 1);
|
|
||||||
char* dest = data;
|
|
||||||
String::CharPointerType t (hex.getCharPointer());
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
int byte = 0;
|
|
||||||
|
|
||||||
for (int loop = 2; --loop >= 0;)
|
|
||||||
{
|
|
||||||
byte <<= 4;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
const beast_wchar c = t.getAndAdvance();
|
|
||||||
|
|
||||||
if (c >= '0' && c <= '9') { byte |= c - '0'; break; }
|
|
||||||
if (c >= 'a' && c <= 'z') { byte |= c - ('a' - 10); break; }
|
|
||||||
if (c >= 'A' && c <= 'Z') { byte |= c - ('A' - 10); break; }
|
|
||||||
|
|
||||||
if (c == 0)
|
|
||||||
{
|
|
||||||
setSize (static_cast <size_t> (dest - data));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*dest++ = (char) byte;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
static char const* const base64EncodingTable = ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+";
|
|
||||||
|
|
||||||
String MemoryBlock::toBase64Encoding() const
|
|
||||||
{
|
|
||||||
const size_t numChars = ((size << 3) + 5) / 6;
|
|
||||||
|
|
||||||
String destString ((unsigned int) size); // store the length, followed by a '.', and then the data.
|
|
||||||
const int initialLen = destString.length();
|
|
||||||
destString.preallocateBytes (sizeof (String::CharPointerType::CharType) * (size_t) initialLen + 2 + numChars);
|
|
||||||
|
|
||||||
String::CharPointerType d (destString.getCharPointer());
|
|
||||||
d += initialLen;
|
|
||||||
d.write ('.');
|
|
||||||
|
|
||||||
for (size_t i = 0; i < numChars; ++i)
|
|
||||||
d.write ((beast_wchar) (std::uint8_t) base64EncodingTable [getBitRange (i * 6, 6)]);
|
|
||||||
|
|
||||||
d.writeNull();
|
|
||||||
return destString;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MemoryBlock::fromBase64Encoding (const String& s)
|
|
||||||
{
|
|
||||||
const int startPos = s.indexOfChar ('.') + 1;
|
|
||||||
|
|
||||||
if (startPos <= 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const int numBytesNeeded = s.substring (0, startPos - 1).getIntValue();
|
|
||||||
|
|
||||||
setSize ((size_t) numBytesNeeded, true);
|
|
||||||
|
|
||||||
const int numChars = s.length() - startPos;
|
|
||||||
|
|
||||||
String::CharPointerType srcChars (s.getCharPointer());
|
|
||||||
srcChars += startPos;
|
|
||||||
int pos = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < numChars; ++i)
|
|
||||||
{
|
|
||||||
const char c = (char) srcChars.getAndAdvance();
|
|
||||||
|
|
||||||
for (int j = 0; j < 64; ++j)
|
|
||||||
{
|
|
||||||
if (base64EncodingTable[j] == c)
|
|
||||||
{
|
|
||||||
setBitRange ((size_t) pos, 6, j);
|
|
||||||
pos += 6;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
@@ -1,275 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Portions of this file are from JUCE.
|
|
||||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
|
||||||
Please visit http://www.juce.com
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
#ifndef BEAST_MODULE_CORE_MEMORY_MEMORYBLOCK_H_INCLUDED
|
|
||||||
#define BEAST_MODULE_CORE_MEMORY_MEMORYBLOCK_H_INCLUDED
|
|
||||||
|
|
||||||
#include <beast/HeapBlock.h>
|
|
||||||
#include <beast/strings/String.h>
|
|
||||||
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/**
|
|
||||||
A class to hold a resizable block of raw data.
|
|
||||||
|
|
||||||
*/
|
|
||||||
class MemoryBlock
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//==============================================================================
|
|
||||||
/** Create an uninitialised block with 0 size. */
|
|
||||||
MemoryBlock() noexcept;
|
|
||||||
|
|
||||||
/** Creates a memory block with a given initial size.
|
|
||||||
|
|
||||||
@param initialSize the size of block to create
|
|
||||||
@param initialiseToZero whether to clear the memory or just leave it uninitialised
|
|
||||||
*/
|
|
||||||
MemoryBlock (const size_t initialSize,
|
|
||||||
bool initialiseToZero = false);
|
|
||||||
|
|
||||||
/** Creates a copy of another memory block. */
|
|
||||||
MemoryBlock (const MemoryBlock& other);
|
|
||||||
|
|
||||||
/** Creates a memory block using a copy of a block of data.
|
|
||||||
|
|
||||||
@param dataToInitialiseFrom some data to copy into this block
|
|
||||||
@param sizeInBytes how much space to use
|
|
||||||
*/
|
|
||||||
MemoryBlock (const void* dataToInitialiseFrom, size_t sizeInBytes);
|
|
||||||
|
|
||||||
/** Destructor. */
|
|
||||||
~MemoryBlock() noexcept;
|
|
||||||
|
|
||||||
/** Copies another memory block onto this one.
|
|
||||||
|
|
||||||
This block will be resized and copied to exactly match the other one.
|
|
||||||
*/
|
|
||||||
MemoryBlock& operator= (const MemoryBlock& other);
|
|
||||||
|
|
||||||
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
|
||||||
MemoryBlock (MemoryBlock&& other) noexcept;
|
|
||||||
MemoryBlock& operator= (MemoryBlock&& other) noexcept;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Standard container interface
|
|
||||||
using iterator = char*;
|
|
||||||
using const_iterator = char const*;
|
|
||||||
inline iterator begin () noexcept { return static_cast <iterator> (getData ()); }
|
|
||||||
inline iterator end () noexcept { return addBytesToPointer (begin (), size); }
|
|
||||||
inline const_iterator cbegin () const noexcept { return static_cast <const_iterator> (getConstData ()); }
|
|
||||||
inline const_iterator cend () const noexcept { return addBytesToPointer (cbegin (), size); }
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Compares two memory blocks.
|
|
||||||
|
|
||||||
@returns true only if the two blocks are the same size and have identical contents.
|
|
||||||
*/
|
|
||||||
bool operator== (const MemoryBlock& other) const noexcept;
|
|
||||||
|
|
||||||
/** Compares two memory blocks.
|
|
||||||
|
|
||||||
@returns true if the two blocks are different sizes or have different contents.
|
|
||||||
*/
|
|
||||||
bool operator!= (const MemoryBlock& other) const noexcept;
|
|
||||||
|
|
||||||
/** Returns true if the data in this MemoryBlock matches the raw bytes passed-in.
|
|
||||||
*/
|
|
||||||
bool matches (const void* data, size_t dataSize) const noexcept;
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Returns a void pointer to the data.
|
|
||||||
|
|
||||||
Note that the pointer returned will probably become invalid when the
|
|
||||||
block is resized.
|
|
||||||
*/
|
|
||||||
void* getData() const noexcept
|
|
||||||
{
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns a void pointer to data as unmodifiable.
|
|
||||||
|
|
||||||
Note that the pointer returned will probably become invalid when the
|
|
||||||
block is resized.
|
|
||||||
*/
|
|
||||||
void const* getConstData() const noexcept
|
|
||||||
{
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns a byte from the memory block.
|
|
||||||
|
|
||||||
This returns a reference, so you can also use it to set a byte.
|
|
||||||
*/
|
|
||||||
template <typename Type>
|
|
||||||
char& operator[] (const Type offset) const noexcept { return data [offset]; }
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Returns the block's current allocated size, in bytes. */
|
|
||||||
size_t getSize() const noexcept { return size; }
|
|
||||||
|
|
||||||
/** Resizes the memory block.
|
|
||||||
|
|
||||||
This will try to keep as much of the block's current content as it can,
|
|
||||||
and can optionally be made to clear any new space that gets allocated at
|
|
||||||
the end of the block.
|
|
||||||
|
|
||||||
@param newSize the new desired size for the block
|
|
||||||
@param initialiseNewSpaceToZero if the block gets enlarged, this determines
|
|
||||||
whether to clear the new section or just leave it
|
|
||||||
uninitialised
|
|
||||||
@see ensureSize
|
|
||||||
*/
|
|
||||||
void setSize (const size_t newSize,
|
|
||||||
bool initialiseNewSpaceToZero = false);
|
|
||||||
|
|
||||||
/** Increases the block's size only if it's smaller than a given size.
|
|
||||||
|
|
||||||
@param minimumSize if the block is already bigger than this size, no action
|
|
||||||
will be taken; otherwise it will be increased to this size
|
|
||||||
@param initialiseNewSpaceToZero if the block gets enlarged, this determines
|
|
||||||
whether to clear the new section or just leave it
|
|
||||||
uninitialised
|
|
||||||
@see setSize
|
|
||||||
*/
|
|
||||||
void ensureSize (const size_t minimumSize,
|
|
||||||
bool initialiseNewSpaceToZero = false);
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Fills the entire memory block with a repeated byte value.
|
|
||||||
|
|
||||||
This is handy for clearing a block of memory to zero.
|
|
||||||
*/
|
|
||||||
void fillWith (std::uint8_t valueToUse) noexcept;
|
|
||||||
|
|
||||||
/** Adds another block of data to the end of this one.
|
|
||||||
The data pointer must not be null. This block's size will be increased accordingly.
|
|
||||||
*/
|
|
||||||
void append (const void* data, size_t numBytes);
|
|
||||||
|
|
||||||
/** Resizes this block to the given size and fills its contents from the supplied buffer.
|
|
||||||
The data pointer must not be null.
|
|
||||||
*/
|
|
||||||
void replaceWith (const void* data, size_t numBytes);
|
|
||||||
|
|
||||||
/** Inserts some data into the block.
|
|
||||||
The dataToInsert pointer must not be null. This block's size will be increased accordingly.
|
|
||||||
If the insert position lies outside the valid range of the block, it will be clipped to
|
|
||||||
within the range before being used.
|
|
||||||
*/
|
|
||||||
void insert (const void* dataToInsert, size_t numBytesToInsert, size_t insertPosition);
|
|
||||||
|
|
||||||
/** Chops out a section of the block.
|
|
||||||
|
|
||||||
This will remove a section of the memory block and close the gap around it,
|
|
||||||
shifting any subsequent data downwards and reducing the size of the block.
|
|
||||||
|
|
||||||
If the range specified goes beyond the size of the block, it will be clipped.
|
|
||||||
*/
|
|
||||||
void removeSection (size_t startByte, size_t numBytesToRemove);
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Copies data into this MemoryBlock from a memory address.
|
|
||||||
|
|
||||||
@param srcData the memory location of the data to copy into this block
|
|
||||||
@param destinationOffset the offset in this block at which the data being copied should begin
|
|
||||||
@param numBytes how much to copy in (if this goes beyond the size of the memory block,
|
|
||||||
it will be clipped so not to do anything nasty)
|
|
||||||
*/
|
|
||||||
void copyFrom (const void* srcData,
|
|
||||||
int destinationOffset,
|
|
||||||
size_t numBytes) noexcept;
|
|
||||||
|
|
||||||
/** Copies data from this MemoryBlock to a memory address.
|
|
||||||
|
|
||||||
@param destData the memory location to write to
|
|
||||||
@param sourceOffset the offset within this block from which the copied data will be read
|
|
||||||
@param numBytes how much to copy (if this extends beyond the limits of the memory block,
|
|
||||||
zeros will be used for that portion of the data)
|
|
||||||
*/
|
|
||||||
void copyTo (void* destData,
|
|
||||||
int sourceOffset,
|
|
||||||
size_t numBytes) const noexcept;
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Exchanges the contents of this and another memory block.
|
|
||||||
No actual copying is required for this, so it's very fast.
|
|
||||||
*/
|
|
||||||
void swapWith (MemoryBlock& other) noexcept;
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Attempts to parse the contents of the block as a zero-terminated UTF8 string. */
|
|
||||||
String toString() const;
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Parses a string of hexadecimal numbers and writes this data into the memory block.
|
|
||||||
|
|
||||||
The block will be resized to the number of valid bytes read from the string.
|
|
||||||
Non-hex characters in the string will be ignored.
|
|
||||||
|
|
||||||
@see String::toHexString()
|
|
||||||
*/
|
|
||||||
void loadFromHexString (const String& sourceHexString);
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Sets a number of bits in the memory block, treating it as a long binary sequence. */
|
|
||||||
void setBitRange (size_t bitRangeStart,
|
|
||||||
size_t numBits,
|
|
||||||
int binaryNumberToApply) noexcept;
|
|
||||||
|
|
||||||
/** Reads a number of bits from the memory block, treating it as one long binary sequence */
|
|
||||||
int getBitRange (size_t bitRangeStart,
|
|
||||||
size_t numBitsToRead) const noexcept;
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
/** Returns a string of characters that represent the binary contents of this block.
|
|
||||||
|
|
||||||
Uses a 64-bit encoding system to allow binary data to be turned into a string
|
|
||||||
of simple non-extended characters, e.g. for storage in XML.
|
|
||||||
|
|
||||||
@see fromBase64Encoding
|
|
||||||
*/
|
|
||||||
String toBase64Encoding() const;
|
|
||||||
|
|
||||||
/** Takes a string of encoded characters and turns it into binary data.
|
|
||||||
|
|
||||||
The string passed in must have been created by to64BitEncoding(), and this
|
|
||||||
block will be resized to recreate the original data block.
|
|
||||||
|
|
||||||
@see toBase64Encoding
|
|
||||||
*/
|
|
||||||
bool fromBase64Encoding (const String& encodedString);
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
//==============================================================================
|
|
||||||
HeapBlock <char> data;
|
|
||||||
size_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
||||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
|
||||||
|
|
||||||
Portions of this file are from JUCE.
|
|
||||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
|
||||||
Please visit http://www.juce.com
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL , DIRECT, 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.
|
|
||||||
*/
|
|
||||||
//==============================================================================
|
|
||||||
|
|
||||||
namespace beast
|
|
||||||
{
|
|
||||||
|
|
||||||
Result::Result() noexcept {}
|
|
||||||
|
|
||||||
Result::Result (const String& message) noexcept
|
|
||||||
: errorMessage (message)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Result::Result (const Result& other)
|
|
||||||
: errorMessage (other.errorMessage)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Result& Result::operator= (const Result& other)
|
|
||||||
{
|
|
||||||
errorMessage = other.errorMessage;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
|
||||||
Result::Result (Result&& other) noexcept
|
|
||||||
: errorMessage (static_cast <String&&> (other.errorMessage))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Result& Result::operator= (Result&& other) noexcept
|
|
||||||
{
|
|
||||||
errorMessage = static_cast <String&&> (other.errorMessage);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool Result::operator== (const Result& other) const noexcept
|
|
||||||
{
|
|
||||||
return errorMessage == other.errorMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Result::operator!= (const Result& other) const noexcept
|
|
||||||
{
|
|
||||||
return errorMessage != other.errorMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result Result::fail (const String& errorMessage) noexcept
|
|
||||||
{
|
|
||||||
return Result (errorMessage.isEmpty() ? "Unknown error" : errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
const String& Result::getErrorMessage() const noexcept
|
|
||||||
{
|
|
||||||
return errorMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Result::wasOk() const noexcept { return errorMessage.isEmpty(); }
|
|
||||||
Result::operator bool() const noexcept { return errorMessage.isEmpty(); }
|
|
||||||
bool Result::failed() const noexcept { return errorMessage.isNotEmpty(); }
|
|
||||||
bool Result::operator!() const noexcept { return errorMessage.isNotEmpty(); }
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user