1 | // © 2016 and later: Unicode, Inc. and others. |
2 | // License & terms of use: http://www.unicode.org/copyright.html |
3 | // Copyright (C) 2009-2011, International Business Machines |
4 | // Corporation and others. All Rights Reserved. |
5 | // |
6 | // Copyright 2007 Google Inc. All Rights Reserved. |
7 | // Author: sanjay@google.com (Sanjay Ghemawat) |
8 | |
9 | #include "unicode/utypes.h" |
10 | #include "unicode/bytestream.h" |
11 | #include "cmemory.h" |
12 | |
13 | U_NAMESPACE_BEGIN |
14 | |
15 | ByteSink::~ByteSink() {} |
16 | |
17 | char* ByteSink::GetAppendBuffer(int32_t min_capacity, |
18 | int32_t /*desired_capacity_hint*/, |
19 | char* scratch, int32_t scratch_capacity, |
20 | int32_t* result_capacity) { |
21 | if (min_capacity < 1 || scratch_capacity < min_capacity) { |
22 | *result_capacity = 0; |
23 | return nullptr; |
24 | } |
25 | *result_capacity = scratch_capacity; |
26 | return scratch; |
27 | } |
28 | |
29 | void ByteSink::Flush() {} |
30 | |
31 | CheckedArrayByteSink::CheckedArrayByteSink(char* outbuf, int32_t capacity) |
32 | : outbuf_(outbuf), capacity_(capacity < 0 ? 0 : capacity), |
33 | size_(0), appended_(0), overflowed_(false) { |
34 | } |
35 | |
36 | CheckedArrayByteSink::~CheckedArrayByteSink() {} |
37 | |
38 | CheckedArrayByteSink& CheckedArrayByteSink::Reset() { |
39 | size_ = appended_ = 0; |
40 | overflowed_ = false; |
41 | return *this; |
42 | } |
43 | |
44 | void CheckedArrayByteSink::Append(const char* bytes, int32_t n) { |
45 | if (n <= 0) { |
46 | return; |
47 | } |
48 | if (n > (INT32_MAX - appended_)) { |
49 | // TODO: Report as integer overflow, not merely buffer overflow. |
50 | appended_ = INT32_MAX; |
51 | overflowed_ = true; |
52 | return; |
53 | } |
54 | appended_ += n; |
55 | int32_t available = capacity_ - size_; |
56 | if (n > available) { |
57 | n = available; |
58 | overflowed_ = true; |
59 | } |
60 | if (n > 0 && bytes != (outbuf_ + size_)) { |
61 | uprv_memcpy(outbuf_ + size_, bytes, n); |
62 | } |
63 | size_ += n; |
64 | } |
65 | |
66 | char* CheckedArrayByteSink::GetAppendBuffer(int32_t min_capacity, |
67 | int32_t /*desired_capacity_hint*/, |
68 | char* scratch, |
69 | int32_t scratch_capacity, |
70 | int32_t* result_capacity) { |
71 | if (min_capacity < 1 || scratch_capacity < min_capacity) { |
72 | *result_capacity = 0; |
73 | return nullptr; |
74 | } |
75 | int32_t available = capacity_ - size_; |
76 | if (available >= min_capacity) { |
77 | *result_capacity = available; |
78 | return outbuf_ + size_; |
79 | } else { |
80 | *result_capacity = scratch_capacity; |
81 | return scratch; |
82 | } |
83 | } |
84 | |
85 | U_NAMESPACE_END |
86 | |