uri_parser 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +6 -0
- data/.rvmrc +1 -0
- data/Gemfile +6 -0
- data/Rakefile +13 -0
- data/ext/uri_parser/basictypes.h +89 -0
- data/ext/uri_parser/extconf.h +6 -0
- data/ext/uri_parser/extconf.rb +50 -0
- data/ext/uri_parser/logging.h +5 -0
- data/ext/uri_parser/scoped_ptr.h +322 -0
- data/ext/uri_parser/string16.cc +95 -0
- data/ext/uri_parser/string16.h +194 -0
- data/ext/uri_parser/uri_parser.cc +87 -0
- data/ext/uri_parser/url_canon.h +872 -0
- data/ext/uri_parser/url_canon_etc.cc +392 -0
- data/ext/uri_parser/url_canon_fileurl.cc +215 -0
- data/ext/uri_parser/url_canon_host.cc +401 -0
- data/ext/uri_parser/url_canon_icu.cc +207 -0
- data/ext/uri_parser/url_canon_icu.h +63 -0
- data/ext/uri_parser/url_canon_internal.cc +427 -0
- data/ext/uri_parser/url_canon_internal.h +453 -0
- data/ext/uri_parser/url_canon_internal_file.h +157 -0
- data/ext/uri_parser/url_canon_ip.cc +737 -0
- data/ext/uri_parser/url_canon_ip.h +101 -0
- data/ext/uri_parser/url_canon_mailtourl.cc +137 -0
- data/ext/uri_parser/url_canon_path.cc +380 -0
- data/ext/uri_parser/url_canon_pathurl.cc +128 -0
- data/ext/uri_parser/url_canon_query.cc +189 -0
- data/ext/uri_parser/url_canon_relative.cc +572 -0
- data/ext/uri_parser/url_canon_stdstring.h +134 -0
- data/ext/uri_parser/url_canon_stdurl.cc +211 -0
- data/ext/uri_parser/url_common.h +48 -0
- data/ext/uri_parser/url_file.h +108 -0
- data/ext/uri_parser/url_parse.cc +760 -0
- data/ext/uri_parser/url_parse.h +336 -0
- data/ext/uri_parser/url_parse_file.cc +243 -0
- data/ext/uri_parser/url_parse_internal.h +112 -0
- data/ext/uri_parser/url_util.cc +553 -0
- data/ext/uri_parser/url_util.h +222 -0
- data/lib/uri_parser.rb +28 -0
- data/lib/uri_parser/version.rb +3 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/uri_parser_spec.rb +54 -0
- data/uri_parser.gemspec +26 -0
- metadata +117 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use 1.9.2@uri_parser --create
|
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require 'rake/extensiontask'
|
5
|
+
Rake::ExtensionTask.new('uri_parser') do |ext|
|
6
|
+
ext.lib_dir = File.join('lib', 'uri_parser')
|
7
|
+
ext.source_pattern = "*.{c,cpp,cc,h}"
|
8
|
+
end
|
9
|
+
|
10
|
+
require "rspec/core/rake_task"
|
11
|
+
RSpec::Core::RakeTask.new(:spec => :compile)
|
12
|
+
task :default => :spec
|
13
|
+
|
@@ -0,0 +1,89 @@
|
|
1
|
+
// Copyright 2001 - 2003 Google Inc. All Rights Reserved
|
2
|
+
|
3
|
+
#ifndef BASE_BASICTYPES_H__
|
4
|
+
#define BASE_BASICTYPES_H__
|
5
|
+
|
6
|
+
typedef unsigned char uint8;
|
7
|
+
typedef unsigned short uint16;
|
8
|
+
typedef unsigned int uint32;
|
9
|
+
typedef unsigned long long uint64;
|
10
|
+
|
11
|
+
const uint8 kuint8max = (( uint8) 0xFF);
|
12
|
+
const uint32 kuint32max = ((uint32) 0xFFFFFFFF);
|
13
|
+
|
14
|
+
// The arraysize(arr) macro returns the # of elements in an array arr.
|
15
|
+
// The expression is a compile-time constant, and therefore can be
|
16
|
+
// used in defining new arrays, for example. If you use arraysize on
|
17
|
+
// a pointer by mistake, you will get a compile-time error.
|
18
|
+
//
|
19
|
+
// One caveat is that arraysize() doesn't accept any array of an
|
20
|
+
// anonymous type or a type defined inside a function. In these rare
|
21
|
+
// cases, you have to use the unsafe ARRAYSIZE() macro below. This is
|
22
|
+
// due to a limitation in C++'s template system. The limitation might
|
23
|
+
// eventually be removed, but it hasn't happened yet.
|
24
|
+
|
25
|
+
// This template function declaration is used in defining arraysize.
|
26
|
+
// Note that the function doesn't need an implementation, as we only
|
27
|
+
// use its type.
|
28
|
+
template <typename T, size_t N>
|
29
|
+
char (&ArraySizeHelper(T (&array)[N]))[N];
|
30
|
+
|
31
|
+
// That gcc wants both of these prototypes seems mysterious. VC, for
|
32
|
+
// its part, can't decide which to use (another mystery). Matching of
|
33
|
+
// template overloads: the final frontier.
|
34
|
+
#ifndef _MSC_VER
|
35
|
+
template <typename T, size_t N>
|
36
|
+
char (&ArraySizeHelper(const T (&array)[N]))[N];
|
37
|
+
#endif
|
38
|
+
|
39
|
+
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
|
40
|
+
|
41
|
+
// ARRAYSIZE performs essentially the same calculation as arraysize,
|
42
|
+
// but can be used on anonymous types or types defined inside
|
43
|
+
// functions. It's less safe than arraysize as it accepts some
|
44
|
+
// (although not all) pointers. Therefore, you should use arraysize
|
45
|
+
// whenever possible.
|
46
|
+
//
|
47
|
+
// The expression ARRAYSIZE(a) is a compile-time constant of type
|
48
|
+
// size_t.
|
49
|
+
//
|
50
|
+
// ARRAYSIZE catches a few type errors. If you see a compiler error
|
51
|
+
//
|
52
|
+
// "warning: division by zero in ..."
|
53
|
+
//
|
54
|
+
// when using ARRAYSIZE, you are (wrongfully) giving it a pointer.
|
55
|
+
// You should only use ARRAYSIZE on statically allocated arrays.
|
56
|
+
//
|
57
|
+
// The following comments are on the implementation details, and can
|
58
|
+
// be ignored by the users.
|
59
|
+
//
|
60
|
+
// ARRAYSIZE(arr) works by inspecting sizeof(arr) (the # of bytes in
|
61
|
+
// the array) and sizeof(*(arr)) (the # of bytes in one array
|
62
|
+
// element). If the former is divisible by the latter, perhaps arr is
|
63
|
+
// indeed an array, in which case the division result is the # of
|
64
|
+
// elements in the array. Otherwise, arr cannot possibly be an array,
|
65
|
+
// and we generate a compiler error to prevent the code from
|
66
|
+
// compiling.
|
67
|
+
//
|
68
|
+
// Since the size of bool is implementation-defined, we need to cast
|
69
|
+
// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final
|
70
|
+
// result has type size_t.
|
71
|
+
//
|
72
|
+
// This macro is not perfect as it wrongfully accepts certain
|
73
|
+
// pointers, namely where the pointer size is divisible by the pointee
|
74
|
+
// size. Since all our code has to go through a 32-bit compiler,
|
75
|
+
// where a pointer is 4 bytes, this means all pointers to a type whose
|
76
|
+
// size is 3 or greater than 4 will be (righteously) rejected.
|
77
|
+
//
|
78
|
+
// Starting with Visual C++ 2005, WinNT.h includes ARRAYSIZE.
|
79
|
+
#define ARRAYSIZE_UNSAFE(a) \
|
80
|
+
((sizeof(a) / sizeof(*(a))) / \
|
81
|
+
static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
|
82
|
+
|
83
|
+
// A macro to disallow the evil copy constructor and operator= functions
|
84
|
+
// This should be used in the private: declarations for a class
|
85
|
+
#define DISALLOW_EVIL_CONSTRUCTORS(TypeName) \
|
86
|
+
TypeName(const TypeName&); \
|
87
|
+
void operator=(const TypeName&)
|
88
|
+
|
89
|
+
#endif // BASE_BASICTYPES_H__
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
extension_name = 'uri_parser'
|
4
|
+
|
5
|
+
$CFLAGS << ' -Wno-deprecated -g '
|
6
|
+
|
7
|
+
if RUBY_PLATFORM =~ /linux|darwin/
|
8
|
+
$libs << ' -lstdc++'
|
9
|
+
$libs << ' -licuuc'
|
10
|
+
else
|
11
|
+
abort <<END_BAD_PLATFORM
|
12
|
+
+----------------------------------------------------------------------------+
|
13
|
+
| This gem is for use only on Linux, and Mac OSX |
|
14
|
+
+----------------------------------------------------------------------------+
|
15
|
+
END_BAD_PLATFORM
|
16
|
+
end
|
17
|
+
|
18
|
+
# Check for compiler. Extract first word so ENV['CC'] can be a program name with arguments.
|
19
|
+
cc = (ENV["CC"] or Config::CONFIG["CC"] or "gcc").split(' ').first
|
20
|
+
unless find_executable(cc)
|
21
|
+
failure "No C compiler found in ${ENV['PATH']}. See mkmf.log for details."
|
22
|
+
end
|
23
|
+
RbConfig::MAKEFILE_CONFIG['CC'] = cc
|
24
|
+
|
25
|
+
def failure s
|
26
|
+
Logging::message s
|
27
|
+
message s+"\n"
|
28
|
+
exit(1)
|
29
|
+
end
|
30
|
+
|
31
|
+
def find_library_or_fail(lib,func)
|
32
|
+
unless have_library(lib, func)
|
33
|
+
failure "Cannot find required library %s (have you installed icu?)" % lib
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def find_header_or_fail hdr
|
38
|
+
unless have_header(hdr)
|
39
|
+
failure "Cannot find required header %s (have you installed icu?)" % hdr
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
find_header_or_fail("unicode/ucnv.h")
|
44
|
+
find_header_or_fail("unicode/ucnv_cb.h")
|
45
|
+
find_header_or_fail("unicode/uidna.h")
|
46
|
+
|
47
|
+
dir_config(extension_name)
|
48
|
+
|
49
|
+
create_header
|
50
|
+
create_makefile(extension_name)
|
@@ -0,0 +1,322 @@
|
|
1
|
+
#ifndef BASE_SCOPED_PTR_H
|
2
|
+
#define BASE_SCOPED_PTR_H
|
3
|
+
|
4
|
+
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
|
5
|
+
// Copyright (c) 2001, 2002 Peter Dimov
|
6
|
+
//
|
7
|
+
// Permission to copy, use, modify, sell and distribute this software
|
8
|
+
// is granted provided this copyright notice appears in all copies.
|
9
|
+
// This software is provided "as is" without express or implied
|
10
|
+
// warranty, and with no claim as to its suitability for any purpose.
|
11
|
+
//
|
12
|
+
// See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation.
|
13
|
+
//
|
14
|
+
|
15
|
+
// scoped_ptr mimics a built-in pointer except that it guarantees deletion
|
16
|
+
// of the object pointed to, either on destruction of the scoped_ptr or via
|
17
|
+
// an explicit reset(). scoped_ptr is a simple solution for simple needs;
|
18
|
+
// use shared_ptr or std::auto_ptr if your needs are more complex.
|
19
|
+
|
20
|
+
// *** NOTE ***
|
21
|
+
// If your scoped_ptr is a class member of class FOO pointing to a
|
22
|
+
// forward declared type BAR (as shown below), then you MUST use a non-inlined
|
23
|
+
// version of the destructor. The destructor of a scoped_ptr (called from
|
24
|
+
// FOO's destructor) must have a complete definition of BAR in order to
|
25
|
+
// destroy it. Example:
|
26
|
+
//
|
27
|
+
// -- foo.h --
|
28
|
+
// class BAR;
|
29
|
+
//
|
30
|
+
// class FOO {
|
31
|
+
// public:
|
32
|
+
// FOO();
|
33
|
+
// ~FOO(); // Required for sources that instantiate class FOO to compile!
|
34
|
+
//
|
35
|
+
// private:
|
36
|
+
// scoped_ptr<BAR> bar_;
|
37
|
+
// };
|
38
|
+
//
|
39
|
+
// -- foo.cc --
|
40
|
+
// #include "foo.h"
|
41
|
+
// FOO::~FOO() {} // Empty, but must be non-inlined to FOO's class definition.
|
42
|
+
|
43
|
+
#include <cstddef> // for std::ptrdiff_t
|
44
|
+
#include <assert.h> // for assert
|
45
|
+
#include <stdlib.h> // for free() decl
|
46
|
+
|
47
|
+
template <typename T>
|
48
|
+
class scoped_ptr {
|
49
|
+
private:
|
50
|
+
|
51
|
+
T* ptr;
|
52
|
+
|
53
|
+
scoped_ptr(scoped_ptr const &);
|
54
|
+
scoped_ptr & operator=(scoped_ptr const &);
|
55
|
+
|
56
|
+
public:
|
57
|
+
|
58
|
+
typedef T element_type;
|
59
|
+
|
60
|
+
explicit scoped_ptr(T* p = 0): ptr(p) {}
|
61
|
+
|
62
|
+
~scoped_ptr() {
|
63
|
+
typedef char type_must_be_complete[sizeof(T)];
|
64
|
+
delete ptr;
|
65
|
+
}
|
66
|
+
|
67
|
+
void reset(T* p = 0) {
|
68
|
+
typedef char type_must_be_complete[sizeof(T)];
|
69
|
+
|
70
|
+
if (ptr != p) {
|
71
|
+
delete ptr;
|
72
|
+
ptr = p;
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
T& operator*() const {
|
77
|
+
assert(ptr != 0);
|
78
|
+
return *ptr;
|
79
|
+
}
|
80
|
+
|
81
|
+
T* operator->() const {
|
82
|
+
assert(ptr != 0);
|
83
|
+
return ptr;
|
84
|
+
}
|
85
|
+
|
86
|
+
bool operator==(T* p) const {
|
87
|
+
return ptr == p;
|
88
|
+
}
|
89
|
+
|
90
|
+
bool operator!=(T* p) const {
|
91
|
+
return ptr != p;
|
92
|
+
}
|
93
|
+
|
94
|
+
T* get() const {
|
95
|
+
return ptr;
|
96
|
+
}
|
97
|
+
|
98
|
+
void swap(scoped_ptr & b) {
|
99
|
+
T* tmp = b.ptr;
|
100
|
+
b.ptr = ptr;
|
101
|
+
ptr = tmp;
|
102
|
+
}
|
103
|
+
|
104
|
+
T* release() {
|
105
|
+
T* tmp = ptr;
|
106
|
+
ptr = 0;
|
107
|
+
return tmp;
|
108
|
+
}
|
109
|
+
|
110
|
+
private:
|
111
|
+
|
112
|
+
// no reason to use these: each scoped_ptr should have its own object
|
113
|
+
template <typename U> bool operator==(scoped_ptr<U> const& p) const;
|
114
|
+
template <typename U> bool operator!=(scoped_ptr<U> const& p) const;
|
115
|
+
};
|
116
|
+
|
117
|
+
template<typename T> inline
|
118
|
+
void swap(scoped_ptr<T>& a, scoped_ptr<T>& b) {
|
119
|
+
a.swap(b);
|
120
|
+
}
|
121
|
+
|
122
|
+
template<typename T> inline
|
123
|
+
bool operator==(T* p, const scoped_ptr<T>& b) {
|
124
|
+
return p == b.get();
|
125
|
+
}
|
126
|
+
|
127
|
+
template<typename T> inline
|
128
|
+
bool operator!=(T* p, const scoped_ptr<T>& b) {
|
129
|
+
return p != b.get();
|
130
|
+
}
|
131
|
+
|
132
|
+
// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to
|
133
|
+
// is guaranteed, either on destruction of the scoped_array or via an explicit
|
134
|
+
// reset(). Use shared_array or std::vector if your needs are more complex.
|
135
|
+
|
136
|
+
template<typename T>
|
137
|
+
class scoped_array {
|
138
|
+
private:
|
139
|
+
|
140
|
+
T* ptr;
|
141
|
+
|
142
|
+
scoped_array(scoped_array const &);
|
143
|
+
scoped_array & operator=(scoped_array const &);
|
144
|
+
|
145
|
+
public:
|
146
|
+
|
147
|
+
typedef T element_type;
|
148
|
+
|
149
|
+
explicit scoped_array(T* p = 0) : ptr(p) {}
|
150
|
+
|
151
|
+
~scoped_array() {
|
152
|
+
typedef char type_must_be_complete[sizeof(T)];
|
153
|
+
delete[] ptr;
|
154
|
+
}
|
155
|
+
|
156
|
+
void reset(T* p = 0) {
|
157
|
+
typedef char type_must_be_complete[sizeof(T)];
|
158
|
+
|
159
|
+
if (ptr != p) {
|
160
|
+
delete [] ptr;
|
161
|
+
ptr = p;
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
T& operator[](std::ptrdiff_t i) const {
|
166
|
+
assert(ptr != 0);
|
167
|
+
assert(i >= 0);
|
168
|
+
return ptr[i];
|
169
|
+
}
|
170
|
+
|
171
|
+
bool operator==(T* p) const {
|
172
|
+
return ptr == p;
|
173
|
+
}
|
174
|
+
|
175
|
+
bool operator!=(T* p) const {
|
176
|
+
return ptr != p;
|
177
|
+
}
|
178
|
+
|
179
|
+
T* get() const {
|
180
|
+
return ptr;
|
181
|
+
}
|
182
|
+
|
183
|
+
void swap(scoped_array & b) {
|
184
|
+
T* tmp = b.ptr;
|
185
|
+
b.ptr = ptr;
|
186
|
+
ptr = tmp;
|
187
|
+
}
|
188
|
+
|
189
|
+
T* release() {
|
190
|
+
T* tmp = ptr;
|
191
|
+
ptr = 0;
|
192
|
+
return tmp;
|
193
|
+
}
|
194
|
+
|
195
|
+
private:
|
196
|
+
|
197
|
+
// no reason to use these: each scoped_array should have its own object
|
198
|
+
template <typename U> bool operator==(scoped_array<U> const& p) const;
|
199
|
+
template <typename U> bool operator!=(scoped_array<U> const& p) const;
|
200
|
+
};
|
201
|
+
|
202
|
+
template<class T> inline
|
203
|
+
void swap(::scoped_array<T>& a, ::scoped_array<T>& b) {
|
204
|
+
a.swap(b);
|
205
|
+
}
|
206
|
+
|
207
|
+
template<typename T> inline
|
208
|
+
bool operator==(T* p, const ::scoped_array<T>& b) {
|
209
|
+
return p == b.get();
|
210
|
+
}
|
211
|
+
|
212
|
+
template<typename T> inline
|
213
|
+
bool operator!=(T* p, const ::scoped_array<T>& b) {
|
214
|
+
return p != b.get();
|
215
|
+
}
|
216
|
+
|
217
|
+
|
218
|
+
// This class wraps the c library function free() in a class that can be
|
219
|
+
// passed as a template argument to scoped_ptr_malloc below.
|
220
|
+
class ScopedPtrMallocFree {
|
221
|
+
public:
|
222
|
+
inline void operator()(void* x) const {
|
223
|
+
free(x);
|
224
|
+
}
|
225
|
+
};
|
226
|
+
|
227
|
+
// scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a
|
228
|
+
// second template argument, the functor used to free the object.
|
229
|
+
|
230
|
+
template<typename T, typename FreeProc = ScopedPtrMallocFree>
|
231
|
+
class scoped_ptr_malloc {
|
232
|
+
private:
|
233
|
+
|
234
|
+
T* ptr;
|
235
|
+
|
236
|
+
scoped_ptr_malloc(scoped_ptr_malloc const &);
|
237
|
+
scoped_ptr_malloc & operator=(scoped_ptr_malloc const &);
|
238
|
+
|
239
|
+
public:
|
240
|
+
|
241
|
+
typedef T element_type;
|
242
|
+
|
243
|
+
explicit scoped_ptr_malloc(T* p = 0): ptr(p) {}
|
244
|
+
|
245
|
+
~scoped_ptr_malloc() {
|
246
|
+
typedef char type_must_be_complete[sizeof(T)];
|
247
|
+
free_((void*) ptr);
|
248
|
+
}
|
249
|
+
|
250
|
+
void reset(T* p = 0) {
|
251
|
+
typedef char type_must_be_complete[sizeof(T)];
|
252
|
+
|
253
|
+
if (ptr != p) {
|
254
|
+
free_((void*) ptr);
|
255
|
+
ptr = p;
|
256
|
+
}
|
257
|
+
}
|
258
|
+
|
259
|
+
T& operator*() const {
|
260
|
+
assert(ptr != 0);
|
261
|
+
return *ptr;
|
262
|
+
}
|
263
|
+
|
264
|
+
T* operator->() const {
|
265
|
+
assert(ptr != 0);
|
266
|
+
return ptr;
|
267
|
+
}
|
268
|
+
|
269
|
+
bool operator==(T* p) const {
|
270
|
+
return ptr == p;
|
271
|
+
}
|
272
|
+
|
273
|
+
bool operator!=(T* p) const {
|
274
|
+
return ptr != p;
|
275
|
+
}
|
276
|
+
|
277
|
+
T* get() const {
|
278
|
+
return ptr;
|
279
|
+
}
|
280
|
+
|
281
|
+
void swap(scoped_ptr_malloc & b) {
|
282
|
+
T* tmp = b.ptr;
|
283
|
+
b.ptr = ptr;
|
284
|
+
ptr = tmp;
|
285
|
+
}
|
286
|
+
|
287
|
+
T* release() {
|
288
|
+
T* tmp = ptr;
|
289
|
+
ptr = 0;
|
290
|
+
return tmp;
|
291
|
+
}
|
292
|
+
|
293
|
+
private:
|
294
|
+
|
295
|
+
// no reason to use these: each scoped_ptr_malloc should have its own object
|
296
|
+
template <typename U, typename GP>
|
297
|
+
bool operator==(scoped_ptr_malloc<U, GP> const& p) const;
|
298
|
+
template <typename U, typename GP>
|
299
|
+
bool operator!=(scoped_ptr_malloc<U, GP> const& p) const;
|
300
|
+
|
301
|
+
static FreeProc const free_;
|
302
|
+
};
|
303
|
+
|
304
|
+
template<typename T, typename FP>
|
305
|
+
FP const scoped_ptr_malloc<T,FP>::free_ = FP();
|
306
|
+
|
307
|
+
template<typename T, typename FP> inline
|
308
|
+
void swap(scoped_ptr_malloc<T,FP>& a, scoped_ptr_malloc<T,FP>& b) {
|
309
|
+
a.swap(b);
|
310
|
+
}
|
311
|
+
|
312
|
+
template<typename T, typename FP> inline
|
313
|
+
bool operator==(T* p, const scoped_ptr_malloc<T,FP>& b) {
|
314
|
+
return p == b.get();
|
315
|
+
}
|
316
|
+
|
317
|
+
template<typename T, typename FP> inline
|
318
|
+
bool operator!=(T* p, const scoped_ptr_malloc<T,FP>& b) {
|
319
|
+
return p != b.get();
|
320
|
+
}
|
321
|
+
|
322
|
+
#endif // #ifndef BASE_SCOPED_PTR_H
|