Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
pistache
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
pistache
Commits
cfb690b3
Unverified
Commit
cfb690b3
authored
Apr 14, 2021
by
Kip
Committed by
GitHub
Apr 14, 2021
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #859 from jacobbogdanov/optional
Upgrade to C++17 and use std::optional
parents
a998e296
258a6198
Changes
24
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
121 additions
and
767 deletions
+121
-767
CMakeLists.txt
CMakeLists.txt
+2
-2
README.md
README.md
+8
-8
debian/control
debian/control
+2
-2
include/pistache/cookie.h
include/pistache/cookie.h
+5
-5
include/pistache/description.h
include/pistache/description.h
+4
-4
include/pistache/http.h
include/pistache/http.h
+1
-1
include/pistache/http_headers.h
include/pistache/http_headers.h
+1
-1
include/pistache/meson.build
include/pistache/meson.build
+0
-1
include/pistache/mime.h
include/pistache/mime.h
+4
-5
include/pistache/optional.h
include/pistache/optional.h
+0
-467
include/pistache/thirdparty/date.h
include/pistache/thirdparty/date.h
+7
-7
include/pistache/transport.h
include/pistache/transport.h
+1
-1
src/common/cookie.cc
src/common/cookie.cc
+26
-17
src/common/description.cc
src/common/description.cc
+6
-6
src/common/http.cc
src/common/http.cc
+3
-3
src/common/http_headers.cc
src/common/http_headers.cc
+3
-3
src/common/mime.cc
src/common/mime.cc
+9
-7
tests/CMakeLists.txt
tests/CMakeLists.txt
+0
-1
tests/cookie_test.cc
tests/cookie_test.cc
+15
-15
tests/headers_test.cc
tests/headers_test.cc
+9
-9
tests/http_client_test.cc
tests/http_client_test.cc
+1
-1
tests/meson.build
tests/meson.build
+0
-2
tests/mime_test.cc
tests/mime_test.cc
+14
-14
tests/optional_test.cc
tests/optional_test.cc
+0
-185
No files found.
CMakeLists.txt
View file @
cfb690b3
...
...
@@ -2,8 +2,8 @@ cmake_minimum_required (VERSION 3.11)
set
(
CMAKE_BUILD_TYPE_INIT Release
)
# CMAKE Pin cxx compiler to CXX1
4 until update to CXX1
7
set
(
CMAKE_CXX_STANDARD 1
4
)
# CMAKE Pin cxx compiler to CXX17
set
(
CMAKE_CXX_STANDARD 1
7
)
set
(
CMAKE_CXX_STANDARD_REQUIRED ON
)
set
(
CMAKE_CXX_EXTENSIONS OFF
)
...
...
README.md
View file @
cfb690b3
...
...
@@ -4,7 +4,7 @@
[
![Build Status
](
https://travis-ci.org/pistacheio/pistache.svg?branch=master
)
](https://travis-ci.org/pistacheio/pistache)
Pistache is a modern and elegant HTTP and REST framework for C++. It is entirely written in pure-C++1
4
and provides a clear and pleasant API.
Pistache is a modern and elegant HTTP and REST framework for C++. It is entirely written in pure-C++1
7
and provides a clear and pleasant API.
## Documentation
...
...
@@ -214,13 +214,13 @@ Be patient, async_test can take some time before completing. And that's it, now
Some other Meson options:
| Option | Default
| Description |
|
-------------------------------|-------------|------------------------------------------------
|
| PISTACHE_USE_SSL | False
| Build server with SSL support |
| PISTACHE_BUILD_TESTS | False
| Build all of the unit tests |
| PISTACHE_ENABLE_NETWORK_TESTS | True
| Run unit tests requiring remote network access |
| PISTACHE_BUILD_EXAMPLES | False
| Build all of the example apps |
| PISTACHE_BUILD_DOCS | False
| Build Doxygen docs |
| Option | Default | Description |
|
----------------------------- | ------- | ----------------------------------------------
|
| PISTACHE_USE_SSL | False | Build server with SSL support |
| PISTACHE_BUILD_TESTS | False | Build all of the unit tests |
| PISTACHE_ENABLE_NETWORK_TESTS | True | Run unit tests requiring remote network access |
| PISTACHE_BUILD_EXAMPLES | False | Build all of the example apps |
| PISTACHE_BUILD_DOCS | False | Build Doxygen docs |
## Continuous Integration Testing
...
...
debian/control
View file @
cfb690b3
...
...
@@ -32,7 +32,7 @@ Depends:
rapidjson-dev (>= 1.1.0)
Description: elegant C++ REST framework
Pistache is a C++ REST framework originally written by Mathieu Stefani at
Datacratic, since maintained by other volunteers. It is written in pure C++1
4
Datacratic, since maintained by other volunteers. It is written in pure C++1
7
with no external dependency and provides a low-level HTTP abstraction.
.
Pistache provides both an HTTP client and server that can be used to create and
...
...
@@ -51,7 +51,7 @@ Depends:
${shlibs:Depends}
Description: elegant C++ REST framework
Pistache is a C++ REST framework originally written by Mathieu Stefani at
Datacratic, since maintained by other volunteers. It is written in pure C++1
4
Datacratic, since maintained by other volunteers. It is written in pure C++1
7
with no external dependency and provides a low-level HTTP abstraction.
.
Pistache provides both an HTTP client and server that can be used to create and
...
...
include/pistache/cookie.h
View file @
cfb690b3
...
...
@@ -9,12 +9,12 @@
#include <ctime>
#include <list>
#include <map>
#include <optional>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <pistache/http_defs.h>
#include <pistache/optional.h>
namespace
Pistache
{
...
...
@@ -30,11 +30,11 @@ namespace Pistache
std
::
string
name
;
std
::
string
value
;
O
ptional
<
std
::
string
>
path
;
O
ptional
<
std
::
string
>
domain
;
O
ptional
<
FullDate
>
expires
;
std
::
o
ptional
<
std
::
string
>
path
;
std
::
o
ptional
<
std
::
string
>
domain
;
std
::
o
ptional
<
FullDate
>
expires
;
O
ptional
<
int
>
maxAge
;
std
::
o
ptional
<
int
>
maxAge
;
bool
secure
;
bool
httpOnly
;
...
...
include/pistache/description.h
View file @
cfb690b3
...
...
@@ -9,6 +9,7 @@
#include <algorithm>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <type_traits>
#include <vector>
...
...
@@ -16,7 +17,6 @@
#include <pistache/http_defs.h>
#include <pistache/iterator_adapter.h>
#include <pistache/mime.h>
#include <pistache/optional.h>
#include <pistache/router.h>
namespace
Pistache
...
...
@@ -154,8 +154,8 @@ namespace Pistache
std
::
string
description
;
std
::
string
termsOfService
;
O
ptional
<
Contact
>
contact
;
O
ptional
<
License
>
license
;
std
::
o
ptional
<
Contact
>
contact
;
std
::
o
ptional
<
License
>
license
;
};
struct
InfoBuilder
...
...
@@ -305,7 +305,7 @@ namespace Pistache
{
}
Group
paths
(
const
std
::
string
&
name
)
const
;
O
ptional
<
Path
>
path
(
const
std
::
string
&
name
,
Http
::
Method
method
)
const
;
std
::
o
ptional
<
Path
>
path
(
const
std
::
string
&
name
,
Http
::
Method
method
)
const
;
group_iterator
add
(
Path
path
);
...
...
include/pistache/http.h
View file @
cfb690b3
...
...
@@ -125,7 +125,7 @@ namespace Pistache
std
::
initializer_list
<
std
::
pair
<
const
std
::
string
,
std
::
string
>>
params
);
void
add
(
std
::
string
name
,
std
::
string
value
);
O
ptional
<
std
::
string
>
get
(
const
std
::
string
&
name
)
const
;
std
::
o
ptional
<
std
::
string
>
get
(
const
std
::
string
&
name
)
const
;
bool
has
(
const
std
::
string
&
name
)
const
;
// Return empty string or "?key1=value1&key2=value2" if query exist
std
::
string
as_str
()
const
;
...
...
include/pistache/http_headers.h
View file @
cfb690b3
...
...
@@ -101,7 +101,7 @@ namespace Pistache
std
::
shared_ptr
<
const
Header
>
tryGet
(
const
std
::
string
&
name
)
const
;
std
::
shared_ptr
<
Header
>
tryGet
(
const
std
::
string
&
name
);
O
ptional
<
Raw
>
tryGetRaw
(
const
std
::
string
&
name
)
const
;
std
::
o
ptional
<
Raw
>
tryGetRaw
(
const
std
::
string
&
name
)
const
;
template
<
typename
H
>
typename
std
::
enable_if
<
IsHeader
<
H
>::
value
,
bool
>::
type
has
()
const
...
...
include/pistache/meson.build
View file @
cfb690b3
...
...
@@ -24,7 +24,6 @@ install_headers([
'mime.h',
'meta.h',
'net.h',
'optional.h',
'os.h',
'peer.h',
'prototype.h',
...
...
include/pistache/mime.h
View file @
cfb690b3
...
...
@@ -8,12 +8,11 @@
#include <cassert>
#include <cmath>
#include <optional>
#include <stdexcept>
#include <string>
#include <unordered_map>
#include <pistache/optional.h>
namespace
Pistache
{
namespace
Http
...
...
@@ -197,10 +196,10 @@ namespace Pistache
std
::
string
raw
()
const
{
return
raw_
;
}
const
O
ptional
<
Q
>&
q
()
const
{
return
q_
;
}
const
std
::
o
ptional
<
Q
>&
q
()
const
{
return
q_
;
}
void
setQuality
(
Q
quality
);
O
ptional
<
std
::
string
>
getParam
(
const
std
::
string
&
name
)
const
;
std
::
o
ptional
<
std
::
string
>
getParam
(
const
std
::
string
&
name
)
const
;
void
setParam
(
const
std
::
string
&
name
,
std
::
string
value
);
std
::
string
toString
()
const
;
...
...
@@ -234,7 +233,7 @@ namespace Pistache
std
::
unordered_map
<
std
::
string
,
std
::
string
>
params
;
O
ptional
<
Q
>
q_
;
std
::
o
ptional
<
Q
>
q_
;
};
inline
bool
operator
==
(
const
MediaType
&
lhs
,
const
MediaType
&
rhs
)
...
...
include/pistache/optional.h
deleted
100644 → 0
View file @
a998e296
/* optional.h
Mathieu Stefani, 27 August 2015
An algebraic data type that can either represent Some Value or None.
This type is the equivalent of the Haskell's Maybe type
*/
#pragma once
#include <array>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iostream>
#include <tuple>
#include <type_traits>
#include <utility>
namespace
Pistache
{
template
<
typename
T
>
class
Optional
;
namespace
types
{
template
<
typename
T
>
class
Some
{
public:
template
<
typename
U
>
friend
class
Pistache
::
Optional
;
explicit
Some
(
const
T
&
val
)
:
val_
(
val
)
{
}
explicit
Some
(
T
&&
val
)
:
val_
(
std
::
move
(
val
))
{
}
private:
T
val_
;
};
class
None
{
};
namespace
impl
{
template
<
typename
Func
>
struct
callable_trait
:
public
callable_trait
<
decltype
(
&
Func
::
operator
())
>
{
};
template
<
typename
Class
,
typename
Ret
,
typename
...
Args
>
struct
callable_trait
<
Ret
(
Class
::*
)(
Args
...)
const
>
{
static
constexpr
size_t
Arity
=
sizeof
...(
Args
);
typedef
std
::
tuple
<
Args
...
>
ArgsType
;
typedef
Ret
ReturnType
;
template
<
size_t
Index
>
struct
Arg
{
static_assert
(
Index
<
Arity
,
"Invalid index"
);
typedef
typename
std
::
tuple_element
<
Index
,
ArgsType
>::
type
Type
;
};
};
}
// namespace impl
template
<
typename
Func
,
bool
IsBindExp
=
std
::
is_bind_expression
<
Func
>
::
value
>
struct
callable_trait
;
/* std::bind returns an unspecified type which contains several overloads
* of operator(). Thus, decltype(&operator()) does not compile since operator()
* is overloaded. To bypass that, we only define the ReturnType for bind
* expressions
*/
template
<
typename
Func
>
struct
callable_trait
<
Func
,
true
>
{
typedef
typename
Func
::
result_type
ReturnType
;
};
template
<
typename
Func
>
struct
callable_trait
<
Func
,
false
>
:
public
impl
::
callable_trait
<
Func
>
{
};
template
<
typename
T
>
struct
is_nothrow_move_constructible
:
std
::
is_nothrow_constructible
<
T
,
typename
std
::
add_rvalue_reference
<
T
>::
type
>
{
};
template
<
class
T
>
struct
is_move_constructible
:
std
::
is_constructible
<
T
,
typename
std
::
add_rvalue_reference
<
T
>::
type
>
{
};
// Workaround for C++14 defect (CWG 1558)
template
<
typename
...
Ts
>
struct
make_void
{
typedef
void
type
;
};
template
<
typename
...
Ts
>
using
void_t
=
typename
make_void
<
Ts
...
>::
type
;
// cppcheck 1.88 (and earlier?) are unable to handle the following template.
// cppcheck reports:
// (error) Syntax Error: AST broken, binary operator '>' doesn't have two
// operands.
// In order to run cppcheck on the rest of this file, we need to cause cppcheck
// to skip the next few lines of code (the code is valid and compiles just
// fine).
#ifndef CPPCHECK
template
<
typename
,
typename
=
void_t
<
>
>
struct
has_equalto_operator
:
std
::
false_type
{
};
#endif
template
<
typename
T
>
struct
has_equalto_operator
<
T
,
void_t
<
decltype
(
std
::
declval
<
T
>
()
==
std
::
declval
<
T
>
())
>>
:
std
::
true_type
{
};
}
// namespace types
inline
types
::
None
None
()
{
return
types
::
None
();
}
template
<
typename
T
,
typename
CleanT
=
typename
std
::
remove_reference
<
T
>
::
type
>
inline
types
::
Some
<
CleanT
>
Some
(
T
&&
value
)
{
return
types
::
Some
<
CleanT
>
(
std
::
forward
<
T
>
(
value
));
}
template
<
typename
T
>
class
Optional
{
public:
Optional
()
{
none_flag
=
NoneMarker
;
}
// TODO: SFINAE-out if T is not trivially_copyable
Optional
(
const
Optional
<
T
>&
other
)
{
if
(
!
other
.
isEmpty
())
{
::
new
(
data
())
T
(
*
other
.
data
());
none_flag
=
ValueMarker
;
}
else
{
none_flag
=
NoneMarker
;
}
}
Optional
(
Optional
<
T
>&&
other
)
noexcept
(
types
::
is_nothrow_move_constructible
<
T
>::
value
)
{
*
this
=
std
::
move
(
other
);
}
template
<
typename
U
>
Optional
(
types
::
Some
<
U
>
some
)
:
none_flag
(
NoneMarker
)
{
static_assert
(
std
::
is_same
<
T
,
U
>::
value
||
std
::
is_convertible
<
U
,
T
>::
value
,
"Types mismatch"
);
from_some_helper
(
std
::
move
(
some
),
types
::
is_move_constructible
<
U
>
());
}
Optional
(
types
::
None
)
{
none_flag
=
NoneMarker
;
}
template
<
typename
U
>
Optional
<
T
>&
operator
=
(
types
::
Some
<
U
>
some
)
{
static_assert
(
std
::
is_same
<
T
,
U
>::
value
||
std
::
is_convertible
<
U
,
T
>::
value
,
"Types mismatch"
);
if
(
none_flag
!=
NoneMarker
)
{
data
()
->~
T
();
}
from_some_helper
(
std
::
move
(
some
),
types
::
is_move_constructible
<
U
>
());
return
*
this
;
}
Optional
<
T
>&
operator
=
(
types
::
None
)
{
if
(
none_flag
!=
NoneMarker
)
{
data
()
->~
T
();
}
none_flag
=
NoneMarker
;
return
*
this
;
}
// TODO: SFINAE-out if T is not trivially_copyable
Optional
<
T
>&
operator
=
(
const
Optional
<
T
>&
other
)
{
if
(
!
other
.
isEmpty
())
{
if
(
none_flag
!=
NoneMarker
)
{
data
()
->~
T
();
}
::
new
(
data
())
T
(
*
other
.
data
());
none_flag
=
ValueMarker
;
}
else
{
if
(
none_flag
!=
NoneMarker
)
{
data
()
->~
T
();
}
none_flag
=
NoneMarker
;
}
return
*
this
;
}
Optional
<
T
>&
operator
=
(
Optional
<
T
>&&
other
)
noexcept
(
types
::
is_nothrow_move_constructible
<
T
>::
value
)
{
if
(
!
other
.
isEmpty
())
{
move_helper
(
std
::
move
(
other
),
types
::
is_move_constructible
<
T
>
());
other
.
none_flag
=
NoneMarker
;
}
else
{
none_flag
=
NoneMarker
;
}
return
*
this
;
}
bool
isEmpty
()
const
{
return
none_flag
==
NoneMarker
;
}
T
getOrElse
(
const
T
&
defaultValue
)
{
if
(
none_flag
!=
NoneMarker
)
{
return
*
constData
();
}
return
defaultValue
;
}
const
T
&
getOrElse
(
const
T
&
defaultValue
)
const
{
if
(
none_flag
!=
NoneMarker
)
{
return
*
constData
();
}
return
defaultValue
;
}
template
<
typename
Func
>
void
orElse
(
Func
func
)
const
{
if
(
isEmpty
())
{
func
();
}
}
T
get
()
{
return
*
constData
();
}
const
T
&
get
()
const
{
return
*
constData
();
}
T
&
unsafeGet
()
const
{
return
*
data
();
}
~
Optional
()
{
if
(
!
isEmpty
())
{
data
()
->~
T
();
}
}
bool
operator
==
(
const
Optional
<
T
>&
other
)
const
{
static_assert
(
types
::
has_equalto_operator
<
T
>::
value
,
"optional<T> requires T to be comparable by equal to operator"
);
return
(
isEmpty
()
&&
other
.
isEmpty
())
||
(
!
isEmpty
()
&&
!
other
.
isEmpty
()
&&
get
()
==
other
.
get
());
}
bool
operator
!=
(
const
Optional
<
T
>&
other
)
const
{
static_assert
(
types
::
has_equalto_operator
<
T
>::
value
,
"optional<T> requires T to be comparable by equal to operator"
);
return
!
(
*
this
==
other
);
}
private:
T
*
constData
()
const
{
return
const_cast
<
T
*
const
>
(
reinterpret_cast
<
const
T
*
const
>
(
bytes
.
data
()));
}
T
*
data
()
const
{
return
const_cast
<
T
*>
(
reinterpret_cast
<
const
T
*>
(
bytes
.
data
()));
}
void
move_helper
(
Optional
<
T
>&&
other
,
std
::
true_type
)
{
::
new
(
data
())
T
(
std
::
move
(
*
other
.
data
()));
none_flag
=
ValueMarker
;
}
void
move_helper
(
Optional
<
T
>&&
other
,
std
::
false_type
)
{
::
new
(
data
())
T
(
*
other
.
data
());
none_flag
=
ValueMarker
;
}
template
<
typename
U
>
void
from_some_helper
(
types
::
Some
<
U
>
some
,
std
::
true_type
)
{
::
new
(
data
())
T
(
std
::
move
(
some
.
val_
));
none_flag
=
ValueMarker
;
}
template
<
typename
U
>
void
from_some_helper
(
types
::
Some
<
U
>
some
,
std
::
false_type
)
{
::
new
(
data
())
T
(
some
.
val_
);
none_flag
=
ValueMarker
;
}
typedef
uint8_t
none_flag_t
;
static
constexpr
none_flag_t
NoneMarker
=
1
;
static
constexpr
none_flag_t
ValueMarker
=
0
;
alignas
(
T
)
std
::
array
<
uint8_t
,
sizeof
(
T
)
>
bytes
;
none_flag_t
none_flag
;
};
#define PistacheCheckSize(Type) \
static_assert(sizeof(Optional<Type>) == sizeof(Type) + alignof(Type), \
"Size differs")
PistacheCheckSize
(
uint8_t
);
PistacheCheckSize
(
uint16_t
);
PistacheCheckSize
(
int
);
PistacheCheckSize
(
void
*
);
PistacheCheckSize
(
std
::
string
);
namespace
details
{
template
<
typename
T
>
struct
RemoveOptional
{
typedef
T
Type
;
};
template
<
typename
T
>
struct
RemoveOptional
<
Optional
<
T
>>
{
typedef
T
Type
;
};
template
<
typename
T
,
typename
Func
>
void
do_static_checks
(
std
::
false_type
)
{
static_assert
(
types
::
callable_trait
<
Func
>::
Arity
==
1
,
"The function must take exactly 1 argument"
);
typedef
typename
types
::
callable_trait
<
Func
>::
template
Arg
<
0
>
::
Type
ArgType
;
typedef
typename
std
::
remove_cv
<
typename
std
::
remove_reference
<
ArgType
>::
type
>::
type
CleanArgType
;
static_assert
(
std
::
is_same
<
CleanArgType
,
T
>::
value
||
std
::
is_convertible
<
CleanArgType
,
T
>::
value
,
"Function parameter type mismatch"
);
}
template
<
typename
T
,
typename
Func
>
void
do_static_checks
(
std
::
true_type
)
{
}
template
<
typename
T
,
typename
Func
>
void
static_checks
()
{
do_static_checks
<
T
,
Func
>
(
std
::
is_bind_expression
<
Func
>
());
}
template
<
typename
Func
>
struct
IsArgMovable
:
public
IsArgMovable
<
decltype
(
&
Func
::
operator
())
>
{
};
template
<
typename
R
,
typename
Class
,
typename
Arg
>
struct
IsArgMovable
<
R
(
Class
::*
)(
Arg
)
const
>
:
public
std
::
is_rvalue_reference
<
Arg
>
{
};
template
<
typename
Func
,
typename
Arg
>
typename
std
::
conditional
<
IsArgMovable
<
Func
>::
value
,
Arg
&&
,
const
Arg
&>::
type
tryMove
(
Arg
&
arg
)
{
return
std
::
move
(
arg
);
}
}
// namespace details
template
<
typename
T
,
typename
Func
>
const
Optional
<
T
>&
optionally_do
(
const
Optional
<
T
>&
option
,
Func
func
)
{
details
::
static_checks
<
T
,
Func
>
();
static_assert
(
std
::
is_same
<
typename
types
::
callable_trait
<
Func
>::
ReturnType
,
void
>::
value
,
"Use optionally_map if you want to return a value"
);
if
(
!
option
.
isEmpty
())
{
func
(
details
::
tryMove
<
Func
>
(
option
.
unsafeGet
()));
}
return
option
;
}
template
<
typename
T
,
typename
Func
>
auto
optionally_map
(
const
Optional
<
T
>&
option
,
Func
func
)
->
Optional
<
typename
types
::
callable_trait
<
Func
>::
ReturnType
>
{
details
::
static_checks
<
T
,
Func
>
();
if
(
!
option
.
isEmpty
())
{
return
Some
(
func
(
details
::
tryMove
<
Func
>
(
option
.
unsafeGet
())));
}
return
None
();
}
template
<
typename
T
,
typename
Func
>
auto
optionally_fmap
(
const
Optional
<
T
>&
option
,
Func
func
)
->
Optional
<
typename
details
::
RemoveOptional
<
typename
types
::
callable_trait
<
Func
>::
ReturnType
>::
Type
>
{
details
::
static_checks
<
T
,
Func
>
();
if
(
!
option
.
isEmpty
())
{
const
auto
&
ret
=
func
(
details
::
tryMove
<
Func
>
(
option
.
unsafeGet
()));
if
(
!
ret
.
isEmpty
())
{
return
Some
(
ret
.
get
());
}
}
return
None
();
}
template
<
typename
T
,
typename
Func
>
Optional
<
T
>
optionally_filter
(
const
Optional
<
T
>&
option
,
Func
func
)
{
details
::
static_checks
<
T
,
Func
>
();
typedef
typename
types
::
callable_trait
<
Func
>::
ReturnType
ReturnType
;
static_assert
(
std
::
is_same
<
ReturnType
,
bool
>::
value
||
std
::
is_convertible
<
ReturnType
,
bool
>::
value
,
"The predicate must return a boolean value"
);
if
(
!
option
.
isEmpty
()
&&
func
(
option
.
get
()))
{
return
Some
(
option
.
get
());
}
return
None
();
}
}
// namespace Pistache
include/pistache/thirdparty/date.h
View file @
cfb690b3
...
...
@@ -3323,13 +3323,13 @@ namespace date
static
CONSTDATA
classify
value
=
std
::
is_convertible
<
Duration
,
std
::
chrono
::
hours
>::
value
?
classify
::
hour
:
std
::
is_convertible
<
Duration
,
std
::
chrono
::
minutes
>::
value
?
classify
::
minute
:
std
::
is_convertible
<
Duration
,
std
::
chrono
::
seconds
>::
value
?
classify
::
second
:
std
::
chrono
::
treat_as_floating_point
<
typename
Duration
::
rep
>::
value
?
classify
::
not_valid
:
classify
::
subsecond
;
?
classify
::
minute
:
std
::
is_convertible
<
Duration
,
std
::
chrono
::
seconds
>::
value
?
classify
::
second
:
std
::
chrono
::
treat_as_floating_point
<
typename
Duration
::
rep
>::
value
?
classify
::
not_valid
:
classify
::
subsecond
;
};
template
<
class
Rep
,
class
Period
>
...
...
include/pistache/transport.h
View file @
cfb690b3
...
...
@@ -8,7 +8,6 @@
#include <pistache/async.h>
#include <pistache/mailbox.h>
#include <pistache/optional.h>
#include <pistache/reactor.h>
#include <pistache/stream.h>
...
...
@@ -16,6 +15,7 @@
#include <deque>
#include <memory>
#include <mutex>
#include <optional>
#include <unordered_map>
namespace
Pistache
...
...
src/common/cookie.cc
View file @
cfb690b3
...
...
@@ -9,6 +9,7 @@
#include <pistache/stream.h>
#include <iterator>
#include <optional>
#include <unordered_map>
namespace
Pistache
...
...
@@ -38,21 +39,21 @@ namespace Pistache
struct
AttributeMatcher
;
template
<
>
struct
AttributeMatcher
<
O
ptional
<
std
::
string
>>
struct
AttributeMatcher
<
std
::
o
ptional
<
std
::
string
>>
{
static
void
match
(
StreamCursor
&
cursor
,
Cookie
*
obj
,
O
ptional
<
std
::
string
>
Cookie
::*
attr
)
std
::
o
ptional
<
std
::
string
>
Cookie
::*
attr
)
{
auto
token
=
matchValue
(
cursor
);
obj
->*
attr
=
Some
(
token
.
text
()
);
obj
->*
attr
=
token
.
text
(
);
}
};
template
<
>
struct
AttributeMatcher
<
O
ptional
<
int
>>
struct
AttributeMatcher
<
std
::
o
ptional
<
int
>>
{
static
void
match
(
StreamCursor
&
cursor
,
Cookie
*
obj
,
O
ptional
<
int
>
Cookie
::*
attr
)
std
::
o
ptional
<
int
>
Cookie
::*
attr
)
{
auto
token
=
matchValue
(
cursor
);
...
...
@@ -70,7 +71,7 @@ namespace Pistache
return
ret
;
};
obj
->*
attr
=
Some
(
strntol
(
token
.
rawText
(),
token
.
size
()
));
obj
->*
attr
=
strntol
(
token
.
rawText
(),
token
.
size
(
));
}
};
...
...
@@ -85,13 +86,13 @@ namespace Pistache
};
template
<
>
struct
AttributeMatcher
<
O
ptional
<
FullDate
>>
struct
AttributeMatcher
<
std
::
o
ptional
<
FullDate
>>
{
static
void
match
(
StreamCursor
&
cursor
,
Cookie
*
obj
,
O
ptional
<
FullDate
>
Cookie
::*
attr
)
std
::
o
ptional
<
FullDate
>
Cookie
::*
attr
)
{
auto
token
=
matchValue
(
cursor
);
obj
->*
attr
=
Some
(
FullDate
::
fromString
(
token
.
text
()
));
obj
->*
attr
=
FullDate
::
fromString
(
token
.
text
(
));
}
};
...
...
@@ -202,23 +203,31 @@ namespace Pistache
void
Cookie
::
write
(
std
::
ostream
&
os
)
const
{
os
<<
name
<<
"="
<<
value
;
optionally_do
(
path
,
[
&
](
const
std
::
string
&
value
)
{
if
(
path
.
has_value
())
{
const
std
::
string
&
value
=
*
path
;
os
<<
"; "
;
os
<<
"Path="
<<
value
;
});
optionally_do
(
domain
,
[
&
](
const
std
::
string
&
value
)
{
}
if
(
domain
.
has_value
())
{
const
std
::
string
&
value
=
*
domain
;
os
<<
"; "
;
os
<<
"Domain="
<<
value
;
});
optionally_do
(
maxAge
,
[
&
](
int
value
)
{
}
if
(
maxAge
.
has_value
())
{
int
value
=
*
maxAge
;
os
<<
"; "
;
os
<<
"Max-Age="
<<
value
;
});
optionally_do
(
expires
,
[
&
](
const
FullDate
&
value
)
{
}
if
(
expires
.
has_value
())
{
const
FullDate
&
value
=
*
expires
;
os
<<
"; "
;
os
<<
"Expires="
;
value
.
write
(
os
);
}
);
}
if
(
secure
)
os
<<
"; Secure"
;
if
(
httpOnly
)
...
...
src/common/description.cc
View file @
cfb690b3
...
...
@@ -158,8 +158,8 @@ namespace Pistache
return
it
->
second
;
}
O
ptional
<
Path
>
PathGroup
::
path
(
const
std
::
string
&
name
,
Http
::
Method
method
)
const
std
::
o
ptional
<
Path
>
PathGroup
::
path
(
const
std
::
string
&
name
,
Http
::
Method
method
)
const
{
auto
group
=
paths
(
name
);
auto
it
=
std
::
find_if
(
std
::
begin
(
group
),
std
::
end
(
group
),
...
...
@@ -167,9 +167,9 @@ namespace Pistache
if
(
it
!=
std
::
end
(
group
))
{
return
Optional
<
Path
>
(
Some
(
*
it
)
);
return
std
::
optional
<
Path
>
(
*
it
);
}
return
Optional
<
Path
>
(
None
())
;
return
std
::
nullopt
;
}
PathGroup
::
group_iterator
PathGroup
::
add
(
Path
path
)
...
...
@@ -258,13 +258,13 @@ namespace Pistache
InfoBuilder
&
InfoBuilder
::
contact
(
std
::
string
name
,
std
::
string
url
,
std
::
string
email
)
{
info_
->
contact
=
Some
(
Contact
(
std
::
move
(
name
),
std
::
move
(
url
),
std
::
move
(
email
)
));
info_
->
contact
=
Contact
(
std
::
move
(
name
),
std
::
move
(
url
),
std
::
move
(
email
));
return
*
this
;
}
InfoBuilder
&
InfoBuilder
::
license
(
std
::
string
name
,
std
::
string
url
)
{
info_
->
license
=
Some
(
License
(
std
::
move
(
name
),
std
::
move
(
url
)
));
info_
->
license
=
License
(
std
::
move
(
name
),
std
::
move
(
url
));
return
*
this
;
}
...
...
src/common/http.cc
View file @
cfb690b3
...
...
@@ -586,13 +586,13 @@ namespace Pistache
params
.
insert
(
std
::
make_pair
(
std
::
move
(
name
),
std
::
move
(
value
)));
}
O
ptional
<
std
::
string
>
Query
::
get
(
const
std
::
string
&
name
)
const
std
::
o
ptional
<
std
::
string
>
Query
::
get
(
const
std
::
string
&
name
)
const
{
auto
it
=
params
.
find
(
name
);
if
(
it
==
std
::
end
(
params
))
return
Optional
<
std
::
string
>
(
None
())
;
return
std
::
nullopt
;
return
Optional
<
std
::
string
>
(
Some
(
it
->
second
)
);
return
std
::
optional
<
std
::
string
>
(
it
->
second
);
}
std
::
string
Query
::
as_str
()
const
...
...
src/common/http_headers.cc
View file @
cfb690b3
...
...
@@ -170,15 +170,15 @@ namespace Pistache
return
header
.
second
;
}
O
ptional
<
Raw
>
Collection
::
tryGetRaw
(
const
std
::
string
&
name
)
const
std
::
o
ptional
<
Raw
>
Collection
::
tryGetRaw
(
const
std
::
string
&
name
)
const
{
auto
it
=
rawHeaders
.
find
(
name
);
if
(
it
==
std
::
end
(
rawHeaders
))
{
return
Optional
<
Raw
>
(
None
())
;
return
std
::
nullopt
;
}
return
Optional
<
Raw
>
(
Some
(
it
->
second
)
);
return
std
::
optional
<
Raw
>
(
it
->
second
);
}
bool
Collection
::
has
(
const
std
::
string
&
name
)
const
...
...
src/common/mime.cc
View file @
cfb690b3
...
...
@@ -240,7 +240,7 @@ namespace Pistache
double
val
;
if
(
!
match_double
(
&
val
,
cursor
))
raise
(
"Invalid quality factor"
);
q_
=
Some
(
Q
::
fromFloat
(
val
)
);
q_
=
Q
::
fromFloat
(
val
);
}
else
{
...
...
@@ -266,17 +266,17 @@ namespace Pistache
}
}
void
MediaType
::
setQuality
(
Q
quality
)
{
q_
=
Some
(
quality
)
;
}
void
MediaType
::
setQuality
(
Q
quality
)
{
q_
=
quality
;
}
O
ptional
<
std
::
string
>
MediaType
::
getParam
(
const
std
::
string
&
name
)
const
std
::
o
ptional
<
std
::
string
>
MediaType
::
getParam
(
const
std
::
string
&
name
)
const
{
auto
it
=
params
.
find
(
name
);
if
(
it
==
std
::
end
(
params
))
{
return
Optional
<
std
::
string
>
(
None
())
;
return
std
::
nullopt
;
}
return
Optional
<
std
::
string
>
(
Some
(
it
->
second
)
);
return
std
::
optional
<
std
::
string
>
(
it
->
second
);
}
void
MediaType
::
setParam
(
const
std
::
string
&
name
,
std
::
string
value
)
...
...
@@ -339,10 +339,12 @@ namespace Pistache
res
+=
suffixString
(
suffix_
);
}
optionally_do
(
q_
,
[
&
res
](
Q
quality
)
{
if
(
q_
.
has_value
())
{
Q
quality
=
*
q_
;
res
+=
"; "
;
res
+=
quality
.
toString
();
}
);
}
for
(
const
auto
&
param
:
params
)
{
...
...
tests/CMakeLists.txt
View file @
cfb690b3
...
...
@@ -36,7 +36,6 @@ pistache_test(mailbox_test)
pistache_test
(
stream_test
)
pistache_test
(
reactor_test
)
pistache_test
(
threadname_test
)
pistache_test
(
optional_test
)
pistache_test
(
log_api_test
)
pistache_test
(
string_logger_test
)
...
...
tests/cookie_test.cc
View file @
cfb690b3
...
...
@@ -28,29 +28,29 @@ TEST(cookie_test, attributes_test)
parse
(
"SID=31d4d96e407aad42; Path=/"
,
[](
const
Cookie
&
c
)
{
ASSERT_EQ
(
c
.
name
,
"SID"
);
ASSERT_EQ
(
c
.
value
,
"31d4d96e407aad42"
);
ASSERT_EQ
(
c
.
path
.
getOrElse
(
""
),
"/"
);
ASSERT_EQ
(
c
.
path
.
value_or
(
""
),
"/"
);
});
parse
(
"SID=31d4d96e407aad42; Path=/; Domain=example.com"
,
[](
const
Cookie
&
c
)
{
ASSERT_EQ
(
c
.
path
.
getOrElse
(
""
),
"/"
);
ASSERT_EQ
(
c
.
domain
.
getOrElse
(
""
),
"example.com"
);
ASSERT_EQ
(
c
.
path
.
value_or
(
""
),
"/"
);
ASSERT_EQ
(
c
.
domain
.
value_or
(
""
),
"example.com"
);
});
parse
(
"lang=en-US; Path=/; Domain=example.com; Max-Age=10"
,
[](
const
Cookie
&
c
)
{
ASSERT_EQ
(
c
.
name
,
"lang"
);
ASSERT_EQ
(
c
.
value
,
"en-US"
);
ASSERT_EQ
(
c
.
path
.
getOrElse
(
""
),
"/"
);
ASSERT_EQ
(
c
.
domain
.
getOrElse
(
""
),
"example.com"
);
ASSERT_EQ
(
c
.
maxAge
.
getOrElse
(
0
),
10
);
ASSERT_EQ
(
c
.
path
.
value_or
(
""
),
"/"
);
ASSERT_EQ
(
c
.
domain
.
value_or
(
""
),
"example.com"
);
ASSERT_EQ
(
c
.
maxAge
.
value_or
(
0
),
10
);
});
parse
(
"lang=en-US; Expires=Wed, 09 Jun 2021 10:18:14 GMT"
,
[](
const
Cookie
&
c
)
{
ASSERT_EQ
(
c
.
name
,
"lang"
);
ASSERT_EQ
(
c
.
value
,
"en-US"
);
auto
expires
=
c
.
expires
.
getOrElse
(
FullDate
());
auto
expires
=
c
.
expires
.
value_or
(
FullDate
());
auto
date
=
expires
.
date
();
using
namespace
std
::
chrono
;
...
...
@@ -61,7 +61,7 @@ TEST(cookie_test, attributes_test)
parse
(
"lang=en-US; Path=/; Domain=example.com;"
,
[](
const
Cookie
&
c
)
{
ASSERT_EQ
(
c
.
name
,
"lang"
);
ASSERT_EQ
(
c
.
value
,
"en-US"
);
ASSERT_EQ
(
c
.
domain
.
getOrElse
(
""
),
"example.com"
);
ASSERT_EQ
(
c
.
domain
.
value_or
(
""
),
"example.com"
);
});
}
...
...
@@ -70,7 +70,7 @@ TEST(cookie_test, bool_test)
parse
(
"SID=31d4d96e407aad42; Path=/; Secure"
,
[](
const
Cookie
&
c
)
{
ASSERT_EQ
(
c
.
name
,
"SID"
);
ASSERT_EQ
(
c
.
value
,
"31d4d96e407aad42"
);
ASSERT_EQ
(
c
.
path
.
getOrElse
(
""
),
"/"
);
ASSERT_EQ
(
c
.
path
.
value_or
(
""
),
"/"
);
ASSERT_TRUE
(
c
.
secure
);
ASSERT_FALSE
(
c
.
httpOnly
);
});
...
...
@@ -78,7 +78,7 @@ TEST(cookie_test, bool_test)
parse
(
"SID=31d4d96e407aad42; Path=/; Secure; HttpOnly"
,
[](
const
Cookie
&
c
)
{
ASSERT_EQ
(
c
.
name
,
"SID"
);
ASSERT_EQ
(
c
.
value
,
"31d4d96e407aad42"
);
ASSERT_EQ
(
c
.
path
.
getOrElse
(
""
),
"/"
);
ASSERT_EQ
(
c
.
path
.
value_or
(
""
),
"/"
);
ASSERT_TRUE
(
c
.
secure
);
ASSERT_TRUE
(
c
.
httpOnly
);
});
...
...
@@ -89,7 +89,7 @@ TEST(cookie_test, ext_test)
parse
(
"lang=en-US; Path=/; Scope=Private"
,
[](
const
Cookie
&
c
)
{
ASSERT_EQ
(
c
.
name
,
"lang"
);
ASSERT_EQ
(
c
.
value
,
"en-US"
);
ASSERT_EQ
(
c
.
path
.
getOrElse
(
""
),
"/"
);
ASSERT_EQ
(
c
.
path
.
value_or
(
""
),
"/"
);
auto
fooIt
=
c
.
ext
.
find
(
"Scope"
);
ASSERT_TRUE
(
fooIt
!=
std
::
end
(
c
.
ext
));
ASSERT_EQ
(
fooIt
->
second
,
"Private"
);
...
...
@@ -99,8 +99,8 @@ TEST(cookie_test, ext_test)
TEST
(
cookie_test
,
write_test
)
{
Cookie
c1
(
"lang"
,
"fr-FR"
);
c1
.
path
=
Some
(
std
::
string
(
"/"
)
);
c1
.
domain
=
Some
(
std
::
string
(
"example.com"
)
);
c1
.
path
=
std
::
string
(
"/"
);
c1
.
domain
=
std
::
string
(
"example.com"
);
std
::
ostringstream
oss
;
oss
<<
c1
;
...
...
@@ -112,8 +112,8 @@ TEST(cookie_test, write_test)
FullDate
::
time_point
expires
=
date
::
sys_days
(
date
::
year
{
118
}
/
2
/
16
)
+
hours
(
17
);
c2
.
path
=
Some
(
std
::
string
(
"/"
)
);
c2
.
expires
=
Some
(
FullDate
(
expires
)
);
c2
.
path
=
std
::
string
(
"/"
);
c2
.
expires
=
FullDate
(
expires
);
oss
.
str
(
""
);
oss
<<
c2
;
...
...
tests/headers_test.cc
View file @
cfb690b3
...
...
@@ -18,7 +18,7 @@ TEST(headers_test, accept)
const
auto
&
mime
=
media
[
0
];
ASSERT_TRUE
(
mime
==
MIME
(
Audio
,
Star
));
ASSERT_TRUE
(
mime
.
q
().
getOrElse
(
Pistache
::
Http
::
Mime
::
Q
(
0
))
==
Pistache
::
Http
::
Mime
::
Q
(
20
));
ASSERT_TRUE
(
mime
.
q
().
value_or
(
Pistache
::
Http
::
Mime
::
Q
(
0
))
==
Pistache
::
Http
::
Mime
::
Q
(
20
));
}
Pistache
::
Http
::
Header
::
Accept
a2
;
...
...
@@ -35,7 +35,7 @@ TEST(headers_test, accept)
const
auto
&
m3
=
media
[
2
];
ASSERT_TRUE
(
m3
==
MIME
(
Text
,
Html
));
auto
level
=
m3
.
getParam
(
"level"
);
ASSERT_TRUE
(
level
.
getOrElse
(
""
)
==
"1"
);
ASSERT_TRUE
(
level
.
value_or
(
""
)
==
"1"
);
const
auto
&
m4
=
media
[
3
];
ASSERT_TRUE
(
m4
==
MIME
(
Star
,
Star
));
}
...
...
@@ -49,13 +49,13 @@ TEST(headers_test, accept)
ASSERT_TRUE
(
media
.
size
()
==
5U
);
ASSERT_TRUE
(
media
[
0
]
==
MIME
(
Text
,
Star
));
ASSERT_TRUE
(
media
[
0
].
q
().
getOrElse
(
Pistache
::
Http
::
Mime
::
Q
(
0
))
==
Pistache
::
Http
::
Mime
::
Q
(
30
));
ASSERT_TRUE
(
media
[
0
].
q
().
value_or
(
Pistache
::
Http
::
Mime
::
Q
(
0
))
==
Pistache
::
Http
::
Mime
::
Q
(
30
));
ASSERT_TRUE
(
media
[
1
]
==
MIME
(
Text
,
Html
));
ASSERT_TRUE
(
media
[
2
]
==
MIME
(
Text
,
Html
));
ASSERT_TRUE
(
media
[
3
]
==
MIME
(
Text
,
Html
));
ASSERT_TRUE
(
media
[
4
]
==
MIME
(
Star
,
Star
));
ASSERT_TRUE
(
media
[
4
].
q
().
getOrElse
(
Pistache
::
Http
::
Mime
::
Q
(
0
))
==
Pistache
::
Http
::
Mime
::
Q
::
fromFloat
(
0.5
));
ASSERT_TRUE
(
media
[
4
].
q
().
value_or
(
Pistache
::
Http
::
Mime
::
Q
(
0
))
==
Pistache
::
Http
::
Mime
::
Q
::
fromFloat
(
0.5
));
}
Pistache
::
Http
::
Header
::
Accept
a4
;
...
...
@@ -574,7 +574,7 @@ TEST(headers_test, content_type)
ASSERT_TRUE
(
"text/html; charset=ISO-8859-4"
==
oss
.
str
());
const
auto
&
mime
=
ct
.
mime
();
ASSERT_TRUE
(
mime
==
MIME
(
Text
,
Html
));
ASSERT_TRUE
(
mime
.
getParam
(
"charset"
).
getOrElse
(
""
)
==
"ISO-8859-4"
);
ASSERT_TRUE
(
mime
.
getParam
(
"charset"
).
value_or
(
""
)
==
"ISO-8859-4"
);
}
TEST
(
headers_test
,
access_control_allow_origin_test
)
...
...
@@ -821,10 +821,10 @@ TEST(headers_test, raw_headers_are_case_insensitive)
step
.
apply
(
cursor
);
// or the header you try and get, it should work:
ASSERT_
FALSE
(
request
.
headers
().
tryGetRaw
(
"Custom-Header"
).
isEmpty
());
ASSERT_
FALSE
(
request
.
headers
().
tryGetRaw
(
"CUSTOM-HEADER"
).
isEmpty
());
ASSERT_
FALSE
(
request
.
headers
().
tryGetRaw
(
"custom-header"
).
isEmpty
());
ASSERT_
FALSE
(
request
.
headers
().
tryGetRaw
(
"CuStOm-HeAdEr"
).
isEmpty
());
ASSERT_
TRUE
(
request
.
headers
().
tryGetRaw
(
"Custom-Header"
).
has_value
());
ASSERT_
TRUE
(
request
.
headers
().
tryGetRaw
(
"CUSTOM-HEADER"
).
has_value
());
ASSERT_
TRUE
(
request
.
headers
().
tryGetRaw
(
"custom-header"
).
has_value
());
ASSERT_
TRUE
(
request
.
headers
().
tryGetRaw
(
"CuStOm-HeAdEr"
).
has_value
());
}
}
...
...
tests/http_client_test.cc
View file @
cfb690b3
...
...
@@ -489,7 +489,7 @@ TEST(http_client_test, client_sends_query)
for
(
auto
entry
:
results
)
{
ASSERT_TRUE
(
query
.
has
(
entry
.
first
));
EXPECT_EQ
(
entry
.
second
,
query
.
get
(
entry
.
first
).
get
());
EXPECT_EQ
(
entry
.
second
,
query
.
get
(
entry
.
first
).
value
());
}
}
...
...
tests/meson.build
View file @
cfb690b3
...
...
@@ -24,7 +24,6 @@ pistache_test_files = [
'stream_test',
'reactor_test',
'threadname_test',
'optional_test',
'log_api_test',
'string_logger_test'
]
...
...
@@ -62,7 +61,6 @@ if cppcheck.found()
'-DCPPCHECK',
'--suppress=*:*tests/*',
'--suppress=*:*subprojects/*',
'--suppress=noExplicitConstructor:include/pistache/optional.h',
'--std=' + get_option('cpp_std')
]
run_target(
...
...
tests/mime_test.cc
View file @
cfb690b3
...
...
@@ -21,9 +21,9 @@ TEST(mime_test, basic_test)
ASSERT_TRUE
(
m2
.
toString
()
==
"application/xhtml+xml"
);
auto
m3
=
MIME
(
Text
,
Plain
);
ASSERT_
TRUE
(
m3
.
q
().
isEmpty
());
ASSERT_
FALSE
(
m3
.
q
().
has_value
());
m3
.
setQuality
(
Q
::
fromFloat
(
0.7
));
ASSERT_TRUE
(
m3
.
q
().
getOrElse
(
Q
(
0
))
==
Q
(
70
));
ASSERT_TRUE
(
m3
.
q
().
value_or
(
Q
(
0
))
==
Q
(
70
));
ASSERT_TRUE
(
m3
.
toString
()
==
"text/plain; q=0.7"
);
...
...
@@ -54,28 +54,28 @@ TEST(mime_test, valid_parsing_test)
{
parse
(
"application/json"
,
[](
const
MediaType
&
m1
)
{
ASSERT_TRUE
(
m1
==
MIME
(
Application
,
Json
));
ASSERT_
TRUE
(
m1
.
q
().
isEmpty
());
ASSERT_
FALSE
(
m1
.
q
().
has_value
());
});
parse
(
"application/xhtml+xml"
,
[](
const
MediaType
&
m2
)
{
ASSERT_TRUE
(
m2
==
MediaType
(
Type
::
Application
,
Subtype
::
Xhtml
,
Suffix
::
Xml
));
ASSERT_
TRUE
(
m2
.
q
().
isEmpty
());
ASSERT_
FALSE
(
m2
.
q
().
has_value
());
});
parse
(
"application/json; q=0.3"
,
[](
const
MediaType
&
m3
)
{
ASSERT_TRUE
(
m3
==
MIME
(
Application
,
Json
));
ASSERT_TRUE
(
m3
.
q
().
getOrElse
(
Q
(
0
))
==
Q
::
fromFloat
(
0.3
));
ASSERT_TRUE
(
m3
.
q
().
value_or
(
Q
(
0
))
==
Q
::
fromFloat
(
0.3
));
});
parse
(
"application/xhtml+xml; q=0.7"
,
[](
const
MediaType
&
m4
)
{
ASSERT_TRUE
(
m4
.
top
()
==
Type
::
Application
);
ASSERT_TRUE
(
m4
.
sub
()
==
Subtype
::
Xhtml
);
ASSERT_TRUE
(
m4
.
suffix
()
==
Suffix
::
Xml
);
ASSERT_TRUE
(
m4
.
q
().
getOrElse
(
Q
(
0
))
==
Q
(
70
));
ASSERT_TRUE
(
m4
.
q
().
value_or
(
Q
(
0
))
==
Q
(
70
));
});
parse
(
"application/xhtml+xml; q=0.78"
,
[](
const
MediaType
&
m5
)
{
ASSERT_TRUE
(
m5
.
q
().
getOrElse
(
Q
(
0
))
==
Q
(
78
));
ASSERT_TRUE
(
m5
.
q
().
value_or
(
Q
(
0
))
==
Q
(
78
));
});
parse
(
"application/vnd.adobe.flash-movie"
,
[](
const
MediaType
&
m6
)
{
...
...
@@ -108,15 +108,15 @@ TEST(mime_test, valid_parsing_test)
parse
(
"text/html; charset=ISO-8859-4"
,
[](
const
MediaType
&
m10
)
{
ASSERT_TRUE
(
m10
==
MIME
(
Text
,
Html
));
ASSERT_
TRUE
(
m10
.
q
().
isEmpty
());
ASSERT_
FALSE
(
m10
.
q
().
has_value
());
auto
charset
=
m10
.
getParam
(
"charset"
);
ASSERT_TRUE
(
charset
.
getOrElse
(
""
)
==
"ISO-8859-4"
);
ASSERT_TRUE
(
charset
.
value_or
(
""
)
==
"ISO-8859-4"
);
});
parse
(
"text/html; q=0.83; charset=ISO-8859-4"
,
[](
const
MediaType
&
m11
)
{
ASSERT_TRUE
(
m11
==
MIME
(
Text
,
Html
));
ASSERT_TRUE
(
m11
.
q
().
getOrElse
(
Q
(
0
))
==
Q
(
83
));
ASSERT_TRUE
(
m11
.
getParam
(
"charset"
).
getOrElse
(
""
)
==
"ISO-8859-4"
);
ASSERT_TRUE
(
m11
.
q
().
value_or
(
Q
(
0
))
==
Q
(
83
));
ASSERT_TRUE
(
m11
.
getParam
(
"charset"
).
value_or
(
""
)
==
"ISO-8859-4"
);
});
}
...
...
@@ -150,15 +150,15 @@ TEST(mime_test, should_parse_case_insensitive_issue_179)
{
parse
(
"Application/Json"
,
[](
const
Mime
::
MediaType
&
mime
)
{
ASSERT_TRUE
(
mime
==
MIME
(
Application
,
Json
));
ASSERT_
TRUE
(
mime
.
q
().
isEmpty
());
ASSERT_
FALSE
(
mime
.
q
().
has_value
());
});
parse
(
"aPpliCAtion/Xhtml+XML"
,
[](
const
MediaType
&
mime
)
{
ASSERT_TRUE
(
mime
==
MediaType
(
Type
::
Application
,
Subtype
::
Xhtml
,
Suffix
::
Xml
));
ASSERT_
TRUE
(
mime
.
q
().
isEmpty
());
ASSERT_
FALSE
(
mime
.
q
().
has_value
());
});
parse
(
"Application/Xhtml+XML; q=0.78"
,
[](
const
MediaType
&
mime
)
{
ASSERT_TRUE
(
mime
.
q
().
getOrElse
(
Q
(
0
))
==
Q
(
78
));
ASSERT_TRUE
(
mime
.
q
().
value_or
(
Q
(
0
))
==
Q
(
78
));
});
}
tests/optional_test.cc
deleted
100644 → 0
View file @
a998e296
#include "gtest/gtest.h"
#include <pistache/optional.h>
using
Pistache
::
Optional
;
TEST
(
optional
,
constructor
)
{
Optional
<
bool
>
value
(
Pistache
::
Some
(
true
));
ASSERT_FALSE
(
value
.
isEmpty
());
EXPECT_TRUE
(
value
.
get
());
}
TEST
(
optional
,
copy_constructor
)
{
Optional
<
bool
>
value
(
Pistache
::
Some
(
true
));
ASSERT_FALSE
(
value
.
isEmpty
());
EXPECT_TRUE
(
value
.
get
());
Optional
<
bool
>
copy_constructed
(
value
);
ASSERT_FALSE
(
copy_constructed
.
isEmpty
());
EXPECT_TRUE
(
copy_constructed
.
get
());
}
TEST
(
optional
,
copy_assignment_operator
)
{
Optional
<
bool
>
value
(
Pistache
::
Some
(
true
));
ASSERT_FALSE
(
value
.
isEmpty
());
Optional
<
bool
>
other
;
EXPECT_TRUE
(
other
.
isEmpty
());
other
=
value
;
ASSERT_FALSE
(
other
.
isEmpty
());
EXPECT_TRUE
(
other
.
get
());
}
TEST
(
optional
,
copy_assignment_operator_for_convertible_type
)
{
Optional
<
bool
>
value
;
EXPECT_TRUE
(
value
.
isEmpty
());
value
=
Pistache
::
Some
(
true
);
ASSERT_FALSE
(
value
.
isEmpty
());
EXPECT_TRUE
(
value
.
get
());
}
TEST
(
optional
,
copy_assignment_operator_for_self_assignment
)
{
Optional
<
bool
>
value
(
Pistache
::
Some
(
true
));
ASSERT_FALSE
(
value
.
isEmpty
());
EXPECT_TRUE
(
value
.
get
());
value
=
value
;
ASSERT_FALSE
(
value
.
isEmpty
());
EXPECT_TRUE
(
value
.
get
());
}
TEST
(
optional
,
move_constructor
)
{
Optional
<
bool
>
value
(
Pistache
::
Some
(
true
));
ASSERT_FALSE
(
value
.
isEmpty
());
EXPECT_TRUE
(
value
.
get
());
Optional
<
bool
>
value_from_move
(
std
::
move
(
value
));
ASSERT_FALSE
(
value_from_move
.
isEmpty
());
EXPECT_TRUE
(
value_from_move
.
get
());
}
TEST
(
optional
,
move_assignment_operator
)
{
Optional
<
bool
>
value
(
Pistache
::
Some
(
true
));
ASSERT_FALSE
(
value
.
isEmpty
());
EXPECT_TRUE
(
value
.
get
());
Optional
<
bool
>
move_assigned
;
move_assigned
=
std
::
move
(
value
);
ASSERT_FALSE
(
move_assigned
.
isEmpty
());
EXPECT_TRUE
(
move_assigned
.
get
());
}
TEST
(
optional
,
integer
)
{
Optional
<
int32_t
>
value
(
Pistache
::
Some
(
1
));
ASSERT_FALSE
(
value
.
isEmpty
());
EXPECT_TRUE
(
value
.
get
());
}
TEST
(
optional
,
constructor_none
)
{
Optional
<
bool
>
value
(
Pistache
::
None
());
EXPECT_TRUE
(
value
.
isEmpty
());
}
TEST
(
optional
,
copy_constructor_none
)
{
Optional
<
bool
>
value
(
Pistache
::
None
());
EXPECT_TRUE
(
value
.
isEmpty
());
Optional
<
bool
>
copy_constructed
(
value
);
EXPECT_TRUE
(
value
.
isEmpty
());
}
TEST
(
optional
,
copy_assignment_operator_none
)
{
Optional
<
bool
>
value
(
Pistache
::
None
());
EXPECT_TRUE
(
value
.
isEmpty
());
Optional
<
bool
>
assigned
=
Pistache
::
None
();
EXPECT_TRUE
(
assigned
.
isEmpty
());
}
TEST
(
optional
,
move_constructor_none
)
{
Optional
<
bool
>
value
(
Pistache
::
None
());
EXPECT_TRUE
(
value
.
isEmpty
());
Optional
<
bool
>
move_constructed
(
std
::
move
(
value
));
EXPECT_TRUE
(
move_constructed
.
isEmpty
());
}
TEST
(
optional
,
move_assignment_operator_none
)
{
Optional
<
bool
>
value
(
Pistache
::
None
());
EXPECT_TRUE
(
value
.
isEmpty
());
Optional
<
bool
>
move_assigned
(
std
::
move
(
value
));
EXPECT_TRUE
(
move_assigned
.
isEmpty
());
}
TEST
(
optional
,
integer_none
)
{
Optional
<
int32_t
>
value
(
Pistache
::
None
());
EXPECT_TRUE
(
value
.
isEmpty
());
}
TEST
(
optional
,
equal_operator_empty_equalto_empty
)
{
Optional
<
int32_t
>
value
(
Pistache
::
None
());
Optional
<
int32_t
>
value2
(
Pistache
::
None
());
EXPECT_EQ
(
value
,
value2
);
}
TEST
(
optional
,
equal_operator_value_equalto_value
)
{
Optional
<
int32_t
>
value
(
Pistache
::
Some
(
1
));
Optional
<
int32_t
>
value2
(
Pistache
::
Some
(
1
));
EXPECT_EQ
(
value
,
value2
);
}
TEST
(
optional
,
equal_operator_empty_notequalto_value
)
{
Optional
<
int32_t
>
value
(
Pistache
::
None
());
Optional
<
int32_t
>
value2
(
Pistache
::
Some
(
2
));
EXPECT_NE
(
value
,
value2
);
}
TEST
(
optional
,
equal_operator_value_notequalto_value
)
{
Optional
<
int32_t
>
value
(
Pistache
::
Some
(
1
));
Optional
<
int32_t
>
value2
(
Pistache
::
Some
(
2
));
EXPECT_NE
(
value
,
value2
);
}
struct
not_comparable
{
bool
operator
==
(
const
not_comparable
&
other
)
const
=
delete
;
};
TEST
(
has_equalto_operator
,
is_comparable_type
)
{
using
Pistache
::
types
::
has_equalto_operator
;
EXPECT_FALSE
(
has_equalto_operator
<
not_comparable
>::
value
);
EXPECT_TRUE
(
has_equalto_operator
<
int
>::
value
);
EXPECT_TRUE
(
has_equalto_operator
<
double
>::
value
);
EXPECT_TRUE
(
has_equalto_operator
<
std
::
string
>::
value
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment