KBufferBuilder.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /*
  2. * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  19. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  22. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  23. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include <AK/StdLibExtras.h>
  27. #include <Kernel/KBufferBuilder.h>
  28. namespace Kernel {
  29. inline bool KBufferBuilder::check_expand(size_t size)
  30. {
  31. if (!m_buffer)
  32. return false;
  33. if ((m_size + size) < m_buffer->capacity())
  34. return true;
  35. if (!m_can_expand)
  36. return false;
  37. if (Checked<size_t>::addition_would_overflow(m_size, size))
  38. return false;
  39. size_t new_buffer_size = m_size + size;
  40. if (Checked<size_t>::addition_would_overflow(new_buffer_size, 1 * MiB))
  41. return false;
  42. new_buffer_size = PAGE_ROUND_UP(new_buffer_size + 1 * MiB);
  43. return m_buffer->expand(new_buffer_size);
  44. }
  45. bool KBufferBuilder::flush()
  46. {
  47. if (!m_buffer)
  48. return false;
  49. m_buffer->set_size(m_size);
  50. return true;
  51. }
  52. OwnPtr<KBuffer> KBufferBuilder::build()
  53. {
  54. if (!flush())
  55. return {};
  56. return make<KBuffer>(move(m_buffer));
  57. }
  58. KBufferBuilder::KBufferBuilder(bool can_expand)
  59. : m_buffer(KBufferImpl::try_create_with_size(4 * MiB, Region::Access::Read | Region::Access::Write))
  60. , m_can_expand(can_expand)
  61. {
  62. }
  63. KBufferBuilder::KBufferBuilder(RefPtr<KBufferImpl>& buffer, bool can_expand)
  64. : m_buffer(buffer)
  65. , m_can_expand(can_expand)
  66. {
  67. if (!m_buffer)
  68. m_buffer = buffer = KBufferImpl::try_create_with_size(4 * MiB, Region::Access::Read | Region::Access::Write);
  69. }
  70. void KBufferBuilder::append_bytes(ReadonlyBytes bytes)
  71. {
  72. if (!check_expand(bytes.size()))
  73. return;
  74. memcpy(insertion_ptr(), bytes.data(), bytes.size());
  75. m_size += bytes.size();
  76. }
  77. void KBufferBuilder::append(const StringView& str)
  78. {
  79. if (str.is_empty())
  80. return;
  81. if (!check_expand(str.length()))
  82. return;
  83. memcpy(insertion_ptr(), str.characters_without_null_termination(), str.length());
  84. m_size += str.length();
  85. }
  86. void KBufferBuilder::append(const char* characters, int length)
  87. {
  88. if (!length)
  89. return;
  90. if (!check_expand(length))
  91. return;
  92. memcpy(insertion_ptr(), characters, length);
  93. m_size += length;
  94. }
  95. void KBufferBuilder::append(char ch)
  96. {
  97. if (!check_expand(1))
  98. return;
  99. insertion_ptr()[0] = ch;
  100. m_size += 1;
  101. }
  102. void KBufferBuilder::append_escaped_for_json(const StringView& string)
  103. {
  104. for (auto ch : string) {
  105. switch (ch) {
  106. case '\e':
  107. append("\\u001B");
  108. break;
  109. case '\b':
  110. append("\\b");
  111. break;
  112. case '\n':
  113. append("\\n");
  114. break;
  115. case '\t':
  116. append("\\t");
  117. break;
  118. case '\"':
  119. append("\\\"");
  120. break;
  121. case '\\':
  122. append("\\\\");
  123. break;
  124. default:
  125. append(ch);
  126. }
  127. }
  128. }
  129. }