KBufferBuilder.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /*
  2. * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/StdLibExtras.h>
  7. #include <Kernel/KBufferBuilder.h>
  8. namespace Kernel {
  9. inline bool KBufferBuilder::check_expand(size_t size)
  10. {
  11. if (!m_buffer)
  12. return false;
  13. if ((m_size + size) < m_buffer->capacity())
  14. return true;
  15. if (!m_can_expand)
  16. return false;
  17. if (Checked<size_t>::addition_would_overflow(m_size, size))
  18. return false;
  19. size_t new_buffer_size = m_size + size;
  20. if (Checked<size_t>::addition_would_overflow(new_buffer_size, 1 * MiB))
  21. return false;
  22. new_buffer_size = page_round_up(new_buffer_size + 1 * MiB);
  23. return m_buffer->expand(new_buffer_size);
  24. }
  25. bool KBufferBuilder::flush()
  26. {
  27. if (!m_buffer)
  28. return false;
  29. m_buffer->set_size(m_size);
  30. return true;
  31. }
  32. OwnPtr<KBuffer> KBufferBuilder::build()
  33. {
  34. if (!flush())
  35. return {};
  36. return adopt_own_if_nonnull(new KBuffer(move(m_buffer)));
  37. }
  38. KBufferBuilder::KBufferBuilder(bool can_expand)
  39. : m_buffer(KBufferImpl::try_create_with_size(4 * MiB, Region::Access::Read | Region::Access::Write))
  40. , m_can_expand(can_expand)
  41. {
  42. }
  43. KBufferBuilder::KBufferBuilder(RefPtr<KBufferImpl>& buffer, bool can_expand)
  44. : m_buffer(buffer)
  45. , m_can_expand(can_expand)
  46. {
  47. if (!m_buffer)
  48. m_buffer = buffer = KBufferImpl::try_create_with_size(4 * MiB, Region::Access::Read | Region::Access::Write);
  49. }
  50. void KBufferBuilder::append_bytes(ReadonlyBytes bytes)
  51. {
  52. if (!check_expand(bytes.size()))
  53. return;
  54. memcpy(insertion_ptr(), bytes.data(), bytes.size());
  55. m_size += bytes.size();
  56. }
  57. void KBufferBuilder::append(const StringView& str)
  58. {
  59. if (str.is_empty())
  60. return;
  61. if (!check_expand(str.length()))
  62. return;
  63. memcpy(insertion_ptr(), str.characters_without_null_termination(), str.length());
  64. m_size += str.length();
  65. }
  66. void KBufferBuilder::append(const char* characters, int length)
  67. {
  68. if (!length)
  69. return;
  70. if (!check_expand(length))
  71. return;
  72. memcpy(insertion_ptr(), characters, length);
  73. m_size += length;
  74. }
  75. void KBufferBuilder::append(char ch)
  76. {
  77. if (!check_expand(1))
  78. return;
  79. insertion_ptr()[0] = ch;
  80. m_size += 1;
  81. }
  82. void KBufferBuilder::append_escaped_for_json(const StringView& string)
  83. {
  84. for (auto ch : string) {
  85. switch (ch) {
  86. case '\e':
  87. append("\\u001B");
  88. break;
  89. case '\b':
  90. append("\\b");
  91. break;
  92. case '\n':
  93. append("\\n");
  94. break;
  95. case '\t':
  96. append("\\t");
  97. break;
  98. case '\"':
  99. append("\\\"");
  100. break;
  101. case '\\':
  102. append("\\\\");
  103. break;
  104. default:
  105. append(ch);
  106. }
  107. }
  108. }
  109. }