KBufferBuilder.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /*
  2. * Copyright (c) 2018-2020, 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/PrintfImplementation.h>
  27. #include <AK/StdLibExtras.h>
  28. #include <Kernel/KBufferBuilder.h>
  29. #include <stdarg.h>
  30. namespace Kernel {
  31. inline bool KBufferBuilder::check_expand(size_t size)
  32. {
  33. if (!m_buffer)
  34. return false;
  35. if ((m_size + size) < m_buffer->capacity())
  36. return true;
  37. if (!m_can_expand)
  38. return false;
  39. if (Checked<size_t>::addition_would_overflow(m_size, size))
  40. return false;
  41. size_t new_buffer_size = m_size + size;
  42. if (Checked<size_t>::addition_would_overflow(new_buffer_size, 1 * MiB))
  43. return false;
  44. new_buffer_size = PAGE_ROUND_UP(new_buffer_size + 1 * MiB);
  45. return m_buffer->expand(new_buffer_size);
  46. }
  47. bool KBufferBuilder::flush()
  48. {
  49. if (!m_buffer)
  50. return false;
  51. m_buffer->set_size(m_size);
  52. return true;
  53. }
  54. OwnPtr<KBuffer> KBufferBuilder::build()
  55. {
  56. if (!flush())
  57. return {};
  58. return make<KBuffer>(move(m_buffer));
  59. }
  60. KBufferBuilder::KBufferBuilder(bool can_expand)
  61. : m_buffer(KBufferImpl::try_create_with_size(4 * MiB, Region::Access::Read | Region::Access::Write))
  62. , m_can_expand(can_expand)
  63. {
  64. }
  65. KBufferBuilder::KBufferBuilder(RefPtr<KBufferImpl>& buffer, bool can_expand)
  66. : m_buffer(buffer)
  67. , m_can_expand(can_expand)
  68. {
  69. if (!m_buffer)
  70. m_buffer = buffer = KBufferImpl::try_create_with_size(4 * MiB, Region::Access::Read | Region::Access::Write);
  71. }
  72. void KBufferBuilder::append_bytes(ReadonlyBytes bytes)
  73. {
  74. if (!check_expand(bytes.size()))
  75. return;
  76. memcpy(insertion_ptr(), bytes.data(), bytes.size());
  77. m_size += bytes.size();
  78. }
  79. void KBufferBuilder::append(const StringView& str)
  80. {
  81. if (str.is_empty())
  82. return;
  83. if (!check_expand(str.length()))
  84. return;
  85. memcpy(insertion_ptr(), str.characters_without_null_termination(), str.length());
  86. m_size += str.length();
  87. }
  88. void KBufferBuilder::append(const char* characters, int length)
  89. {
  90. if (!length)
  91. return;
  92. if (!check_expand(length))
  93. return;
  94. memcpy(insertion_ptr(), characters, length);
  95. m_size += length;
  96. }
  97. void KBufferBuilder::append(char ch)
  98. {
  99. if (!check_expand(1))
  100. return;
  101. insertion_ptr()[0] = ch;
  102. m_size += 1;
  103. }
  104. void KBufferBuilder::appendvf(const char* fmt, va_list ap)
  105. {
  106. printf_internal([this](char*&, char ch) {
  107. append(ch);
  108. },
  109. nullptr, fmt, ap);
  110. }
  111. void KBufferBuilder::appendf(const char* fmt, ...)
  112. {
  113. va_list ap;
  114. va_start(ap, fmt);
  115. appendvf(fmt, ap);
  116. va_end(ap);
  117. }
  118. void KBufferBuilder::append_escaped_for_json(const StringView& string)
  119. {
  120. for (auto ch : string) {
  121. switch (ch) {
  122. case '\e':
  123. append("\\u001B");
  124. break;
  125. case '\b':
  126. append("\\b");
  127. break;
  128. case '\n':
  129. append("\\n");
  130. break;
  131. case '\t':
  132. append("\\t");
  133. break;
  134. case '\"':
  135. append("\\\"");
  136. break;
  137. case '\\':
  138. append("\\\\");
  139. break;
  140. default:
  141. append(ch);
  142. }
  143. }
  144. }
  145. }