/proc/self/cwd/cpp/htmlparser/defer.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Executes a block of code (lambda) after the function returns, or a block |
2 | | // ends. |
3 | | // Useful for multiple (and nested) returns inside a function. |
4 | | // |
5 | | // Usage: |
6 | | // In the following example fd file descriptor is closed after MyFunction |
7 | | // returns from any location. |
8 | | // |
9 | | // void MyObject::MyFunction() { |
10 | | // fd = open(...); |
11 | | // other_fd = open(...); |
12 | | // stream = open(...); |
13 | | // counter = 0; |
14 | | // |
15 | | // defer(fd.close()); |
16 | | // // Can include multiple statements. |
17 | | // defer({ |
18 | | // other_fd.close(); |
19 | | // stream.close(); |
20 | | // counter++; |
21 | | // }); |
22 | | // |
23 | | // // do something with above descriptor. |
24 | | // . if (condition) { |
25 | | // return; |
26 | | // . } else { |
27 | | // . for (..) { |
28 | | // if (other_condition) return; |
29 | | // . } |
30 | | // . return; |
31 | | // } |
32 | | // |
33 | | // defer() converts the block into lambda and captures all the variables in |
34 | | // current block by reference. So instead of writing the following: |
35 | | // defer([&]() { |
36 | | // delete mylocal_fd; |
37 | | // fd_counter++; |
38 | | // }); |
39 | | // |
40 | | // one can write: |
41 | | // defer({ |
42 | | // delete mylocal_fd; |
43 | | // fd_counter++; |
44 | | // }); |
45 | | |
46 | | #ifndef CPP_HTMLPARSER_DEFER_H_ |
47 | | #define CPP_HTMLPARSER_DEFER_H_ |
48 | | |
49 | | #include <functional> |
50 | | |
51 | | namespace htmlparser { |
52 | | |
53 | | #define DEFER_CONCAT_(a, b) a ## b |
54 | | #define DEFER_CONCAT(a, b) DEFER_CONCAT_(a, b) |
55 | | |
56 | | class Defer { |
57 | | public: |
58 | | template<typename Callable> |
59 | | Defer(Callable&& defer_call) : defer_call_(std::forward<Callable>( |
60 | 1.55M | defer_call)) {} parser.cc:htmlparser::Defer::Defer<htmlparser::Parser::AfterHeadIM()::$_1>(htmlparser::Parser::AfterHeadIM()::$_1&&) Line | Count | Source | 60 | 321 | defer_call)) {} |
parser.cc:htmlparser::Defer::Defer<htmlparser::Parser::InTableIM()::$_2>(htmlparser::Parser::InTableIM()::$_2&&) Line | Count | Source | 60 | 1.55M | defer_call)) {} |
tokenizer.cc:htmlparser::Defer::Defer<htmlparser::Tokenizer::ReadScript()::$_0>(htmlparser::Tokenizer::ReadScript()::$_0&&) Line | Count | Source | 60 | 2.65k | defer_call)) {} |
tokenizer.cc:htmlparser::Defer::Defer<htmlparser::Tokenizer::ReadComment()::$_1>(htmlparser::Tokenizer::ReadComment()::$_1&&) Line | Count | Source | 60 | 1.25k | defer_call)) {} |
|
61 | | |
62 | 0 | Defer(Defer&& other) : defer_call_(std::move(other.defer_call_)) { |
63 | 0 | other.defer_call_ = nullptr; |
64 | 0 | } |
65 | | |
66 | 1.55M | ~Defer() { |
67 | 1.55M | if (defer_call_) defer_call_(); |
68 | 1.55M | } |
69 | | |
70 | | private: |
71 | | Defer(const Defer&) = delete; |
72 | | void operator=(const Defer&) = delete; |
73 | | |
74 | | std::function<void(void)> defer_call_; |
75 | | }; |
76 | | |
77 | | // Define a defer() keyword, whose behavior is similar to golang. |
78 | 1.55M | #define defer(fn) Defer DEFER_CONCAT(__defer__, __LINE__) = [&] ( ) { fn ; } parser.cc:htmlparser::Parser::AfterHeadIM()::$_1::operator()() const Line | Count | Source | 78 | 321 | #define defer(fn) Defer DEFER_CONCAT(__defer__, __LINE__) = [&] ( ) { fn ; } |
parser.cc:htmlparser::Parser::InTableIM()::$_2::operator()() const Line | Count | Source | 78 | 1.55M | #define defer(fn) Defer DEFER_CONCAT(__defer__, __LINE__) = [&] ( ) { fn ; } |
tokenizer.cc:htmlparser::Tokenizer::ReadScript()::$_0::operator()() const Line | Count | Source | 78 | 2.65k | #define defer(fn) Defer DEFER_CONCAT(__defer__, __LINE__) = [&] ( ) { fn ; } |
tokenizer.cc:htmlparser::Tokenizer::ReadComment()::$_1::operator()() const Line | Count | Source | 78 | 2.04k | #define defer(fn) Defer DEFER_CONCAT(__defer__, __LINE__) = [&] ( ) { fn ; } |
|
79 | | |
80 | | } // namespace htmlparser |
81 | | |
82 | | #endif // CPP_HTMLPARSER_DEFER_H_ |