KBufferBuilder.cpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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 try_make<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. void KBufferBuilder::append_bytes(ReadonlyBytes bytes)
  44. {
  45. if (!check_expand(bytes.size()))
  46. return;
  47. memcpy(insertion_ptr(), bytes.data(), bytes.size());
  48. m_size += bytes.size();
  49. }
  50. void KBufferBuilder::append(const StringView& str)
  51. {
  52. if (str.is_empty())
  53. return;
  54. if (!check_expand(str.length()))
  55. return;
  56. memcpy(insertion_ptr(), str.characters_without_null_termination(), str.length());
  57. m_size += str.length();
  58. }
  59. void KBufferBuilder::append(const char* characters, int length)
  60. {
  61. if (!length)
  62. return;
  63. if (!check_expand(length))
  64. return;
  65. memcpy(insertion_ptr(), characters, length);
  66. m_size += length;
  67. }
  68. void KBufferBuilder::append(char ch)
  69. {
  70. if (!check_expand(1))
  71. return;
  72. insertion_ptr()[0] = ch;
  73. m_size += 1;
  74. }
  75. void KBufferBuilder::append_escaped_for_json(const StringView& string)
  76. {
  77. for (auto ch : string) {
  78. switch (ch) {
  79. case '\e':
  80. append("\\u001B");
  81. break;
  82. case '\b':
  83. append("\\b");
  84. break;
  85. case '\n':
  86. append("\\n");
  87. break;
  88. case '\t':
  89. append("\\t");
  90. break;
  91. case '\"':
  92. append("\\\"");
  93. break;
  94. case '\\':
  95. append("\\\\");
  96. break;
  97. default:
  98. append(ch);
  99. }
  100. }
  101. }
  102. }