KBufferBuilder.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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 (Checked<size_t>::addition_would_overflow(m_size, size))
  16. return false;
  17. size_t new_buffer_size = m_size + size;
  18. if (Checked<size_t>::addition_would_overflow(new_buffer_size, 1 * MiB))
  19. return false;
  20. auto rounded_new_buffer_size_or_error = Memory::page_round_up(new_buffer_size + 1 * MiB);
  21. if (rounded_new_buffer_size_or_error.is_error()) {
  22. return false;
  23. }
  24. auto new_buffer_or_error = KBuffer::try_create_with_size(rounded_new_buffer_size_or_error.value());
  25. if (new_buffer_or_error.is_error())
  26. return false;
  27. auto new_buffer = new_buffer_or_error.release_value();
  28. memcpy(new_buffer->data(), m_buffer->data(), m_buffer->size());
  29. m_buffer = move(new_buffer);
  30. return true;
  31. }
  32. bool KBufferBuilder::flush()
  33. {
  34. if (!m_buffer)
  35. return false;
  36. m_buffer->set_size(m_size);
  37. return true;
  38. }
  39. OwnPtr<KBuffer> KBufferBuilder::build()
  40. {
  41. if (!flush())
  42. return {};
  43. return move(m_buffer);
  44. }
  45. ErrorOr<KBufferBuilder> KBufferBuilder::try_create()
  46. {
  47. auto buffer = TRY(KBuffer::try_create_with_size(4 * MiB, Memory::Region::Access::ReadWrite));
  48. return KBufferBuilder { move(buffer) };
  49. }
  50. KBufferBuilder::KBufferBuilder(NonnullOwnPtr<KBuffer> buffer)
  51. : m_buffer(move(buffer))
  52. {
  53. }
  54. ErrorOr<void> KBufferBuilder::append_bytes(ReadonlyBytes bytes)
  55. {
  56. if (!check_expand(bytes.size()))
  57. return ENOMEM;
  58. memcpy(insertion_ptr(), bytes.data(), bytes.size());
  59. m_size += bytes.size();
  60. return {};
  61. }
  62. ErrorOr<void> KBufferBuilder::append(StringView str)
  63. {
  64. if (str.is_empty())
  65. return {};
  66. if (!check_expand(str.length()))
  67. return ENOMEM;
  68. memcpy(insertion_ptr(), str.characters_without_null_termination(), str.length());
  69. m_size += str.length();
  70. return {};
  71. }
  72. ErrorOr<void> KBufferBuilder::append(const char* characters, int length)
  73. {
  74. if (!length)
  75. return {};
  76. if (!check_expand(length))
  77. return ENOMEM;
  78. memcpy(insertion_ptr(), characters, length);
  79. m_size += length;
  80. return {};
  81. }
  82. ErrorOr<void> KBufferBuilder::append(char ch)
  83. {
  84. if (!check_expand(1))
  85. return ENOMEM;
  86. insertion_ptr()[0] = ch;
  87. m_size += 1;
  88. return {};
  89. }
  90. ErrorOr<void> KBufferBuilder::append_escaped_for_json(StringView string)
  91. {
  92. for (auto ch : string) {
  93. switch (ch) {
  94. case '\b':
  95. TRY(append("\\b"));
  96. break;
  97. case '\n':
  98. TRY(append("\\n"));
  99. break;
  100. case '\t':
  101. TRY(append("\\t"));
  102. break;
  103. case '\"':
  104. TRY(append("\\\""));
  105. break;
  106. case '\\':
  107. TRY(append("\\\\"));
  108. break;
  109. default:
  110. if (ch >= 0 && ch <= 0x1f)
  111. TRY(appendff("\\u{:04x}", ch));
  112. else
  113. TRY(append(ch));
  114. }
  115. }
  116. return {};
  117. }
  118. }