StringPrintStream.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /*
  2. * Copyright (C) 2012 Apple Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
  14. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  16. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
  17. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  18. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  19. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  20. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  21. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  23. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #include "config.h"
  26. #include "StringPrintStream.h"
  27. #include <stdarg.h>
  28. #include <stdio.h>
  29. #include <wtf/FastMalloc.h>
  30. #include <wtf/StringExtras.h>
  31. namespace WTF {
  32. StringPrintStream::StringPrintStream()
  33. : m_buffer(m_inlineBuffer)
  34. , m_next(0)
  35. , m_size(sizeof(m_inlineBuffer))
  36. {
  37. m_buffer[0] = 0; // Make sure that we always have a null terminator.
  38. }
  39. StringPrintStream::~StringPrintStream()
  40. {
  41. if (m_buffer == m_inlineBuffer)
  42. return;
  43. fastFree(m_buffer);
  44. }
  45. void StringPrintStream::vprintf(const char* format, va_list argList)
  46. {
  47. ASSERT_WITH_SECURITY_IMPLICATION(m_next < m_size);
  48. ASSERT(!m_buffer[m_next]);
  49. va_list firstPassArgList;
  50. #if OS(WINDOWS)
  51. firstPassArgList = argList;
  52. #else
  53. va_copy(firstPassArgList, argList);
  54. #endif
  55. int numberOfBytesNotIncludingTerminatorThatWouldHaveBeenWritten =
  56. vsnprintf(m_buffer + m_next, m_size - m_next, format, firstPassArgList);
  57. int numberOfBytesThatWouldHaveBeenWritten =
  58. numberOfBytesNotIncludingTerminatorThatWouldHaveBeenWritten + 1;
  59. if (m_next + numberOfBytesThatWouldHaveBeenWritten <= m_size) {
  60. m_next += numberOfBytesNotIncludingTerminatorThatWouldHaveBeenWritten;
  61. return; // This means that vsnprintf() succeeded.
  62. }
  63. increaseSize(m_next + numberOfBytesThatWouldHaveBeenWritten);
  64. int numberOfBytesNotIncludingTerminatorThatWereWritten =
  65. vsnprintf(m_buffer + m_next, m_size - m_next, format, argList);
  66. int numberOfBytesThatWereWritten = numberOfBytesNotIncludingTerminatorThatWereWritten + 1;
  67. ASSERT_UNUSED(numberOfBytesThatWereWritten, m_next + numberOfBytesThatWereWritten <= m_size);
  68. m_next += numberOfBytesNotIncludingTerminatorThatWereWritten;
  69. ASSERT_WITH_SECURITY_IMPLICATION(m_next < m_size);
  70. ASSERT(!m_buffer[m_next]);
  71. }
  72. CString StringPrintStream::toCString()
  73. {
  74. ASSERT(m_next == strlen(m_buffer));
  75. return CString(m_buffer, m_next);
  76. }
  77. void StringPrintStream::reset()
  78. {
  79. m_next = 0;
  80. m_buffer[0] = 0;
  81. }
  82. String StringPrintStream::toString()
  83. {
  84. ASSERT(m_next == strlen(m_buffer));
  85. return String::fromUTF8(m_buffer, m_next);
  86. }
  87. void StringPrintStream::increaseSize(size_t newSize)
  88. {
  89. ASSERT(newSize > m_size);
  90. ASSERT(newSize > sizeof(m_inlineBuffer));
  91. // Use exponential resizing to reduce thrashing.
  92. m_size = newSize << 1;
  93. // Use fastMalloc instead of fastRealloc because we know that for the sizes we're using,
  94. // fastRealloc will just do malloc+free anyway. Also, this simplifies the code since
  95. // we can't realloc the inline buffer.
  96. char* newBuffer = static_cast<char*>(fastMalloc(m_size));
  97. memcpy(newBuffer, m_buffer, m_next + 1);
  98. if (m_buffer != m_inlineBuffer)
  99. fastFree(m_buffer);
  100. m_buffer = newBuffer;
  101. }
  102. } // namespace WTF