KBufferBuilder.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  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. new_buffer_size = Memory::page_round_up(new_buffer_size + 1 * MiB);
  21. return m_buffer->expand(new_buffer_size);
  22. }
  23. bool KBufferBuilder::flush()
  24. {
  25. if (!m_buffer)
  26. return false;
  27. m_buffer->set_size(m_size);
  28. return true;
  29. }
  30. OwnPtr<KBuffer> KBufferBuilder::build()
  31. {
  32. if (!flush())
  33. return {};
  34. return try_make<KBuffer>(move(m_buffer));
  35. }
  36. KBufferBuilder::KBufferBuilder()
  37. : m_buffer(KBufferImpl::try_create_with_size(4 * MiB, Memory::Region::Access::ReadWrite))
  38. {
  39. }
  40. void KBufferBuilder::append_bytes(ReadonlyBytes bytes)
  41. {
  42. if (!check_expand(bytes.size()))
  43. return;
  44. memcpy(insertion_ptr(), bytes.data(), bytes.size());
  45. m_size += bytes.size();
  46. }
  47. void KBufferBuilder::append(const StringView& str)
  48. {
  49. if (str.is_empty())
  50. return;
  51. if (!check_expand(str.length()))
  52. return;
  53. memcpy(insertion_ptr(), str.characters_without_null_termination(), str.length());
  54. m_size += str.length();
  55. }
  56. void KBufferBuilder::append(const char* characters, int length)
  57. {
  58. if (!length)
  59. return;
  60. if (!check_expand(length))
  61. return;
  62. memcpy(insertion_ptr(), characters, length);
  63. m_size += length;
  64. }
  65. void KBufferBuilder::append(char ch)
  66. {
  67. if (!check_expand(1))
  68. return;
  69. insertion_ptr()[0] = ch;
  70. m_size += 1;
  71. }
  72. void KBufferBuilder::append_escaped_for_json(const StringView& string)
  73. {
  74. for (auto ch : string) {
  75. switch (ch) {
  76. case '\e':
  77. append("\\u001B");
  78. break;
  79. case '\b':
  80. append("\\b");
  81. break;
  82. case '\n':
  83. append("\\n");
  84. break;
  85. case '\t':
  86. append("\\t");
  87. break;
  88. case '\"':
  89. append("\\\"");
  90. break;
  91. case '\\':
  92. append("\\\\");
  93. break;
  94. default:
  95. append(ch);
  96. }
  97. }
  98. }
  99. }