Coverage Report

Created: 2024-09-08 06:07

/proc/self/cwd/external/com_google_absl/absl/strings/internal/str_format/extension.h
Line
Count
Source (jump to first uncovered line)
1
//
2
// Copyright 2017 The Abseil Authors.
3
//
4
// Licensed under the Apache License, Version 2.0 (the "License");
5
// you may not use this file except in compliance with the License.
6
// You may obtain a copy of the License at
7
//
8
//      https://www.apache.org/licenses/LICENSE-2.0
9
//
10
// Unless required by applicable law or agreed to in writing, software
11
// distributed under the License is distributed on an "AS IS" BASIS,
12
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
// See the License for the specific language governing permissions and
14
// limitations under the License.
15
//
16
#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
17
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
18
19
20
#include <cstddef>
21
#include <cstdint>
22
#include <cstring>
23
#include <ostream>
24
#include <string>
25
26
#include "absl/base/config.h"
27
#include "absl/strings/internal/str_format/output.h"
28
#include "absl/strings/string_view.h"
29
30
namespace absl {
31
ABSL_NAMESPACE_BEGIN
32
33
enum class FormatConversionChar : uint8_t;
34
enum class FormatConversionCharSet : uint64_t;
35
enum class LengthMod : std::uint8_t { h, hh, l, ll, L, j, z, t, q, none };
36
37
namespace str_format_internal {
38
39
class FormatRawSinkImpl {
40
 public:
41
  // Implicitly convert from any type that provides the hook function as
42
  // described above.
43
  template <typename T, decltype(str_format_internal::InvokeFlush(
44
                            std::declval<T*>(), string_view()))* = nullptr>
45
  FormatRawSinkImpl(T* raw)  // NOLINT
46
4.96k
      : sink_(raw), write_(&FormatRawSinkImpl::Flush<T>) {}
absl::str_format_internal::FormatRawSinkImpl::FormatRawSinkImpl<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, (void*)0>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*)
Line
Count
Source
46
4.96k
      : sink_(raw), write_(&FormatRawSinkImpl::Flush<T>) {}
Unexecuted instantiation: absl::str_format_internal::FormatRawSinkImpl::FormatRawSinkImpl<std::__1::basic_ostream<char, std::__1::char_traits<char> >, (void*)0>(std::__1::basic_ostream<char, std::__1::char_traits<char> >*)
Unexecuted instantiation: absl::str_format_internal::FormatRawSinkImpl::FormatRawSinkImpl<absl::str_format_internal::FILERawSink, (void*)0>(absl::str_format_internal::FILERawSink*)
Unexecuted instantiation: absl::str_format_internal::FormatRawSinkImpl::FormatRawSinkImpl<absl::str_format_internal::BufferRawSink, (void*)0>(absl::str_format_internal::BufferRawSink*)
47
48
4.96k
  void Write(string_view s) { write_(sink_, s); }
49
50
  template <typename T>
51
0
  static FormatRawSinkImpl Extract(T s) {
52
0
    return s.sink_;
53
0
  }
54
55
 private:
56
  template <typename T>
57
4.96k
  static void Flush(void* r, string_view s) {
58
4.96k
    str_format_internal::InvokeFlush(static_cast<T*>(r), s);
59
4.96k
  }
void absl::str_format_internal::FormatRawSinkImpl::Flush<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(void*, absl::string_view)
Line
Count
Source
57
4.96k
  static void Flush(void* r, string_view s) {
58
4.96k
    str_format_internal::InvokeFlush(static_cast<T*>(r), s);
59
4.96k
  }
Unexecuted instantiation: void absl::str_format_internal::FormatRawSinkImpl::Flush<std::__1::basic_ostream<char, std::__1::char_traits<char> > >(void*, absl::string_view)
Unexecuted instantiation: void absl::str_format_internal::FormatRawSinkImpl::Flush<absl::str_format_internal::FILERawSink>(void*, absl::string_view)
Unexecuted instantiation: void absl::str_format_internal::FormatRawSinkImpl::Flush<absl::str_format_internal::BufferRawSink>(void*, absl::string_view)
60
61
  void* sink_;
62
  void (*write_)(void*, string_view);
63
};
64
65
// An abstraction to which conversions write their string data.
66
class FormatSinkImpl {
67
 public:
68
4.96k
  explicit FormatSinkImpl(FormatRawSinkImpl raw) : raw_(raw) {}
69
70
4.96k
  ~FormatSinkImpl() { Flush(); }
71
72
4.96k
  void Flush() {
73
4.96k
    raw_.Write(string_view(buf_, static_cast<size_t>(pos_ - buf_)));
74
4.96k
    pos_ = buf_;
75
4.96k
  }
76
77
4.48k
  void Append(size_t n, char c) {
78
4.48k
    if (n == 0) return;
79
722
    size_ += n;
80
722
    auto raw_append = [&](size_t count) {
81
722
      memset(pos_, c, count);
82
722
      pos_ += count;
83
722
    };
84
722
    while (n > Avail()) {
85
0
      n -= Avail();
86
0
      if (Avail() > 0) {
87
0
        raw_append(Avail());
88
0
      }
89
0
      Flush();
90
0
    }
91
722
    raw_append(n);
92
722
  }
93
94
9.92k
  void Append(string_view v) {
95
9.92k
    size_t n = v.size();
96
9.92k
    if (n == 0) return;
97
4.96k
    size_ += n;
98
4.96k
    if (n >= Avail()) {
99
0
      Flush();
100
0
      raw_.Write(v);
101
0
      return;
102
0
    }
103
4.96k
    memcpy(pos_, v.data(), n);
104
4.96k
    pos_ += n;
105
4.96k
  }
106
107
0
  size_t size() const { return size_; }
108
109
  // Put 'v' to 'sink' with specified width, precision, and left flag.
110
  bool PutPaddedString(string_view v, int width, int precision, bool left);
111
112
  template <typename T>
113
  T Wrap() {
114
    return T(this);
115
  }
116
117
  template <typename T>
118
  static FormatSinkImpl* Extract(T* s) {
119
    return s->sink_;
120
  }
121
122
 private:
123
5.68k
  size_t Avail() const {
124
5.68k
    return static_cast<size_t>(buf_ + sizeof(buf_) - pos_);
125
5.68k
  }
126
127
  FormatRawSinkImpl raw_;
128
  size_t size_ = 0;
129
  char* pos_ = buf_;
130
  char buf_[1024];
131
};
132
133
enum class Flags : uint8_t {
134
  kBasic = 0,
135
  kLeft = 1 << 0,
136
  kShowPos = 1 << 1,
137
  kSignCol = 1 << 2,
138
  kAlt = 1 << 3,
139
  kZero = 1 << 4,
140
  // This is not a real flag. It just exists to turn off kBasic when no other
141
  // flags are set. This is for when width/precision are specified, or a length
142
  // modifier affects the behavior ("%lc").
143
  kNonBasic = 1 << 5,
144
};
145
146
0
constexpr Flags operator|(Flags a, Flags b) {
147
0
  return static_cast<Flags>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
148
0
}
149
150
11.7k
constexpr bool FlagsContains(Flags haystack, Flags needle) {
151
11.7k
  return (static_cast<uint8_t>(haystack) & static_cast<uint8_t>(needle)) ==
152
11.7k
         static_cast<uint8_t>(needle);
153
11.7k
}
154
155
std::string FlagsToString(Flags v);
156
157
0
inline std::ostream& operator<<(std::ostream& os, Flags v) {
158
0
  return os << FlagsToString(v);
159
0
}
160
161
// clang-format off
162
#define ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, X_SEP) \
163
  /* text */ \
164
0
  X_VAL(c) X_SEP X_VAL(s) X_SEP \
165
0
  /* ints */ \
166
0
  X_VAL(d) X_SEP X_VAL(i) X_SEP X_VAL(o) X_SEP \
167
0
  X_VAL(u) X_SEP X_VAL(x) X_SEP X_VAL(X) X_SEP \
168
0
  /* floats */ \
169
0
  X_VAL(f) X_SEP X_VAL(F) X_SEP X_VAL(e) X_SEP X_VAL(E) X_SEP \
170
1.22k
  X_VAL(g) X_SEP X_VAL(G) X_SEP X_VAL(a) X_SEP X_VAL(A) X_SEP \
171
0
  /* misc */ \
172
0
  X_VAL(n) X_SEP X_VAL(p) X_SEP X_VAL(v)
173
// clang-format on
174
175
// This type should not be referenced, it exists only to provide labels
176
// internally that match the values declared in FormatConversionChar in
177
// str_format.h. This is meant to allow internal libraries to use the same
178
// declared interface type as the public interface
179
// (absl::StrFormatConversionChar) while keeping the definition in a public
180
// header.
181
// Internal libraries should use the form
182
// `FormatConversionCharInternal::c`, `FormatConversionCharInternal::kNone` for
183
// comparisons.  Use in switch statements is not recommended due to a bug in how
184
// gcc 4.9 -Wswitch handles declared but undefined enums.
185
struct FormatConversionCharInternal {
186
  FormatConversionCharInternal() = delete;
187
188
 private:
189
  // clang-format off
190
  enum class Enum : uint8_t {
191
    c, s,                    // text
192
    d, i, o, u, x, X,        // int
193
    f, F, e, E, g, G, a, A,  // float
194
    n, p, v,                    // misc
195
    kNone
196
  };
197
  // clang-format on
198
 public:
199
#define ABSL_INTERNAL_X_VAL(id)              \
200
  static constexpr FormatConversionChar id = \
201
      static_cast<FormatConversionChar>(Enum::id);
202
  ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
203
#undef ABSL_INTERNAL_X_VAL
204
  static constexpr FormatConversionChar kNone =
205
      static_cast<FormatConversionChar>(Enum::kNone);
206
};
207
// clang-format on
208
209
0
inline FormatConversionChar FormatConversionCharFromChar(char c) {
210
0
  switch (c) {
211
0
#define ABSL_INTERNAL_X_VAL(id) \
212
0
  case #id[0]:                  \
213
0
    return FormatConversionCharInternal::id;
214
0
    ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
215
0
#undef ABSL_INTERNAL_X_VAL
216
0
  }
217
0
  return FormatConversionCharInternal::kNone;
218
0
}
219
220
1.21k
inline bool FormatConversionCharIsUpper(FormatConversionChar c) {
221
1.21k
  if (c == FormatConversionCharInternal::X ||
222
1.21k
      c == FormatConversionCharInternal::F ||
223
1.21k
      c == FormatConversionCharInternal::E ||
224
1.21k
      c == FormatConversionCharInternal::G ||
225
1.21k
      c == FormatConversionCharInternal::A) {
226
0
    return true;
227
1.21k
  } else {
228
1.21k
    return false;
229
1.21k
  }
230
1.21k
}
231
232
2.48k
inline bool FormatConversionCharIsFloat(FormatConversionChar c) {
233
2.48k
  if (c == FormatConversionCharInternal::a ||
234
2.48k
      c == FormatConversionCharInternal::e ||
235
2.48k
      c == FormatConversionCharInternal::f ||
236
2.48k
      c == FormatConversionCharInternal::g ||
237
2.48k
      c == FormatConversionCharInternal::A ||
238
2.48k
      c == FormatConversionCharInternal::E ||
239
2.48k
      c == FormatConversionCharInternal::F ||
240
2.48k
      c == FormatConversionCharInternal::G) {
241
2.48k
    return true;
242
2.48k
  } else {
243
0
    return false;
244
0
  }
245
2.48k
}
246
247
1.22k
inline char FormatConversionCharToChar(FormatConversionChar c) {
248
1.22k
  if (c == FormatConversionCharInternal::kNone) {
249
0
    return '\0';
250
251
0
#define ABSL_INTERNAL_X_VAL(e)                       \
252
15.9k
  } else if (c == FormatConversionCharInternal::e) { \
253
1.22k
    return #e[0];
254
0
#define ABSL_INTERNAL_X_SEP
255
1.22k
  ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL,
256
0
                                         ABSL_INTERNAL_X_SEP)
257
0
  } else {
258
0
    return '\0';
259
0
  }
260
261
1.22k
#undef ABSL_INTERNAL_X_VAL
262
1.22k
#undef ABSL_INTERNAL_X_SEP
263
1.22k
}
264
265
// The associated char.
266
0
inline std::ostream& operator<<(std::ostream& os, FormatConversionChar v) {
267
0
  char c = FormatConversionCharToChar(v);
268
0
  if (!c) c = '?';
269
0
  return os << c;
270
0
}
271
272
struct FormatConversionSpecImplFriend;
273
274
class FormatConversionSpecImpl {
275
 public:
276
  // Width and precision are not specified, no flags are set.
277
2.48k
  bool is_basic() const { return flags_ == Flags::kBasic; }
278
1.25k
  bool has_left_flag() const { return FlagsContains(flags_, Flags::kLeft); }
279
910
  bool has_show_pos_flag() const {
280
910
    return FlagsContains(flags_, Flags::kShowPos);
281
910
  }
282
910
  bool has_sign_col_flag() const {
283
910
    return FlagsContains(flags_, Flags::kSignCol);
284
910
  }
285
1.25k
  bool has_alt_flag() const { return FlagsContains(flags_, Flags::kAlt); }
286
1.25k
  bool has_zero_flag() const { return FlagsContains(flags_, Flags::kZero); }
287
288
0
  LengthMod length_mod() const { return length_mod_; }
289
290
23.5k
  FormatConversionChar conversion_char() const {
291
    // Keep this field first in the struct . It generates better code when
292
    // accessing it when ConversionSpec is passed by value in registers.
293
23.5k
    static_assert(offsetof(FormatConversionSpecImpl, conv_) == 0, "");
294
23.5k
    return conv_;
295
23.5k
  }
296
297
0
  void set_conversion_char(FormatConversionChar c) { conv_ = c; }
298
299
  // Returns the specified width. If width is unspecfied, it returns a negative
300
  // value.
301
2.48k
  int width() const { return width_; }
302
  // Returns the specified precision. If precision is unspecfied, it returns a
303
  // negative value.
304
3.70k
  int precision() const { return precision_; }
305
306
  template <typename T>
307
  T Wrap() {
308
    return T(*this);
309
  }
310
311
 private:
312
  friend struct str_format_internal::FormatConversionSpecImplFriend;
313
  FormatConversionChar conv_ = FormatConversionCharInternal::kNone;
314
  Flags flags_;
315
  LengthMod length_mod_ = LengthMod::none;
316
  int width_;
317
  int precision_;
318
};
319
320
struct FormatConversionSpecImplFriend final {
321
4.96k
  static void SetFlags(Flags f, FormatConversionSpecImpl* conv) {
322
4.96k
    conv->flags_ = f;
323
4.96k
  }
324
0
  static void SetLengthMod(LengthMod l, FormatConversionSpecImpl* conv) {
325
0
    conv->length_mod_ = l;
326
0
  }
327
  static void SetConversionChar(FormatConversionChar c,
328
4.96k
                                FormatConversionSpecImpl* conv) {
329
4.96k
    conv->conv_ = c;
330
4.96k
  }
331
4.96k
  static void SetWidth(int w, FormatConversionSpecImpl* conv) {
332
4.96k
    conv->width_ = w;
333
4.96k
  }
334
4.96k
  static void SetPrecision(int p, FormatConversionSpecImpl* conv) {
335
4.96k
    conv->precision_ = p;
336
4.96k
  }
337
1.22k
  static std::string FlagsToString(const FormatConversionSpecImpl& spec) {
338
1.22k
    return str_format_internal::FlagsToString(spec.flags_);
339
1.22k
  }
340
};
341
342
// Type safe OR operator.
343
// We need this for two reasons:
344
//  1. operator| on enums makes them decay to integers and the result is an
345
//     integer. We need the result to stay as an enum.
346
//  2. We use "enum class" which would not work even if we accepted the decay.
347
constexpr FormatConversionCharSet FormatConversionCharSetUnion(
348
0
    FormatConversionCharSet a) {
349
0
  return a;
350
0
}
351
352
template <typename... CharSet>
353
constexpr FormatConversionCharSet FormatConversionCharSetUnion(
354
0
    FormatConversionCharSet a, CharSet... rest) {
355
0
  return static_cast<FormatConversionCharSet>(
356
0
      static_cast<uint64_t>(a) |
357
0
      static_cast<uint64_t>(FormatConversionCharSetUnion(rest...)));
358
0
}
Unexecuted instantiation: absl::FormatConversionCharSet absl::str_format_internal::FormatConversionCharSetUnion<absl::FormatConversionCharSet>(absl::FormatConversionCharSet, absl::FormatConversionCharSet)
Unexecuted instantiation: absl::FormatConversionCharSet absl::str_format_internal::FormatConversionCharSetUnion<absl::FormatConversionCharSet, absl::FormatConversionCharSet>(absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet)
Unexecuted instantiation: absl::FormatConversionCharSet absl::str_format_internal::FormatConversionCharSetUnion<absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet>(absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet)
Unexecuted instantiation: absl::FormatConversionCharSet absl::str_format_internal::FormatConversionCharSetUnion<absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet>(absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet)
Unexecuted instantiation: absl::FormatConversionCharSet absl::str_format_internal::FormatConversionCharSetUnion<absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet>(absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet)
Unexecuted instantiation: absl::FormatConversionCharSet absl::str_format_internal::FormatConversionCharSetUnion<absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet>(absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet)
Unexecuted instantiation: absl::FormatConversionCharSet absl::str_format_internal::FormatConversionCharSetUnion<absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet>(absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet, absl::FormatConversionCharSet)
359
360
4.96k
constexpr uint64_t FormatConversionCharToConvInt(FormatConversionChar c) {
361
4.96k
  return uint64_t{1} << (1 + static_cast<uint8_t>(c));
362
4.96k
}
363
364
0
constexpr uint64_t FormatConversionCharToConvInt(char conv) {
365
0
  return
366
0
#define ABSL_INTERNAL_CHAR_SET_CASE(c)                                 \
367
0
  conv == #c[0]                                                        \
368
0
      ? FormatConversionCharToConvInt(FormatConversionCharInternal::c) \
369
0
      :
370
0
      ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
371
0
#undef ABSL_INTERNAL_CHAR_SET_CASE
372
0
                  conv == '*'
373
0
          ? 1
374
0
          : 0;
375
0
}
376
377
0
constexpr FormatConversionCharSet FormatConversionCharToConvValue(char conv) {
378
0
  return static_cast<FormatConversionCharSet>(
379
0
      FormatConversionCharToConvInt(conv));
380
0
}
381
382
struct FormatConversionCharSetInternal {
383
#define ABSL_INTERNAL_CHAR_SET_CASE(c)         \
384
  static constexpr FormatConversionCharSet c = \
385
      FormatConversionCharToConvValue(#c[0]);
386
  ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
387
#undef ABSL_INTERNAL_CHAR_SET_CASE
388
389
  // Used for width/precision '*' specification.
390
  static constexpr FormatConversionCharSet kStar =
391
      FormatConversionCharToConvValue('*');
392
393
  static constexpr FormatConversionCharSet kIntegral =
394
      FormatConversionCharSetUnion(d, i, u, o, x, X);
395
  static constexpr FormatConversionCharSet kFloating =
396
      FormatConversionCharSetUnion(a, e, f, g, A, E, F, G);
397
  static constexpr FormatConversionCharSet kNumeric =
398
      FormatConversionCharSetUnion(kIntegral, kFloating);
399
  static constexpr FormatConversionCharSet kPointer = p;
400
};
401
402
// Type safe OR operator.
403
// We need this for two reasons:
404
//  1. operator| on enums makes them decay to integers and the result is an
405
//     integer. We need the result to stay as an enum.
406
//  2. We use "enum class" which would not work even if we accepted the decay.
407
constexpr FormatConversionCharSet operator|(FormatConversionCharSet a,
408
0
                                            FormatConversionCharSet b) {
409
0
  return FormatConversionCharSetUnion(a, b);
410
0
}
411
412
// Overloaded conversion functions to support absl::ParsedFormat.
413
// Get a conversion with a single character in it.
414
0
constexpr FormatConversionCharSet ToFormatConversionCharSet(char c) {
415
0
  return static_cast<FormatConversionCharSet>(
416
0
      FormatConversionCharToConvValue(c));
417
0
}
418
419
// Get a conversion with a single character in it.
420
constexpr FormatConversionCharSet ToFormatConversionCharSet(
421
0
    FormatConversionCharSet c) {
422
0
  return c;
423
0
}
424
425
template <typename T>
426
void ToFormatConversionCharSet(T) = delete;
427
428
// Checks whether `c` exists in `set`.
429
0
constexpr bool Contains(FormatConversionCharSet set, char c) {
430
0
  return (static_cast<uint64_t>(set) &
431
0
          static_cast<uint64_t>(FormatConversionCharToConvValue(c))) != 0;
432
0
}
433
434
// Checks whether all the characters in `c` are contained in `set`
435
constexpr bool Contains(FormatConversionCharSet set,
436
0
                        FormatConversionCharSet c) {
437
0
  return (static_cast<uint64_t>(set) & static_cast<uint64_t>(c)) ==
438
0
         static_cast<uint64_t>(c);
439
0
}
440
441
// Checks whether all the characters in `c` are contained in `set`
442
4.96k
constexpr bool Contains(FormatConversionCharSet set, FormatConversionChar c) {
443
4.96k
  return (static_cast<uint64_t>(set) & FormatConversionCharToConvInt(c)) != 0;
444
4.96k
}
445
446
// Return capacity - used, clipped to a minimum of 0.
447
0
inline size_t Excess(size_t used, size_t capacity) {
448
0
  return used < capacity ? capacity - used : 0;
449
0
}
450
451
}  // namespace str_format_internal
452
453
ABSL_NAMESPACE_END
454
}  // namespace absl
455
456
#endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_