< prev index next >

src/hotspot/share/utilities/formatBuffer.hpp

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.

@@ -61,14 +61,37 @@
   char* buffer() { return _buf; }
   int size() { return bufsz; }
 
  private:
   FormatBuffer(const FormatBuffer &); // prevent copies
-  char _buffer[bufsz];
 
  protected:
+  char _buffer[bufsz];
   inline FormatBuffer();
+  inline void appendv(const char* format, va_list ap)  ATTRIBUTE_PRINTF(2, 0);
+};
+
+// Use malloc'ed buffer if static buffer is not enough.
+template <size_t bufsz = FormatBufferBase::BufferSize>
+class FormatBufferEx : public FormatBuffer<bufsz> {
+ public:
+  inline FormatBufferEx();
+  ~FormatBufferEx(){
+    if (_dyn_buffer != NULL) {
+      ::free(_dyn_buffer);
+    }
+  }
+  inline void append(const char* format, ...)  ATTRIBUTE_PRINTF(2, 3);
+  inline void print(const char* format, ...)  ATTRIBUTE_PRINTF(2, 3);
+  inline void printv(const char* format, va_list argp) ATTRIBUTE_PRINTF(2, 0);
+
+  int size() { return _buffer_size; }
+
+ private:
+  inline void prepare_buffer(bool is_append, const char* format, va_list argp);
+  char *_dyn_buffer;
+  size_t _buffer_size;
 };
 
 template <size_t bufsz>
 FormatBuffer<bufsz>::FormatBuffer(const char * format, ...) : FormatBufferBase(_buffer) {
   va_list argp;

@@ -100,18 +123,72 @@
   jio_vsnprintf(_buf, bufsz, format, argp);
 }
 
 template <size_t bufsz>
 void FormatBuffer<bufsz>::append(const char* format, ...) {
+  va_list argp;
+  va_start(argp, format);
+  appendv(format, argp);
+  va_end(argp);
+}
+
+template <size_t bufsz>
+void FormatBuffer<bufsz>::appendv(const char* format, va_list argp) {
   // Given that the constructor does a vsnprintf we can assume that
   // _buf is already initialized.
   size_t len = strlen(_buf);
   char* buf_end = _buf + len;
 
+  jio_vsnprintf(buf_end, bufsz - len, format, argp);
+}
+
+template <size_t bufsz>
+FormatBufferEx<bufsz>::FormatBufferEx() : FormatBuffer<bufsz>(), _dyn_buffer(NULL), _buffer_size(bufsz) {
+  // Do nothing.
+}
+
+template <size_t bufsz>
+void FormatBufferEx<bufsz>::print(const char * format, ...) {
   va_list argp;
   va_start(argp, format);
-  jio_vsnprintf(buf_end, bufsz - len, format, argp);
+  printv(format, argp);
+  va_end(argp);
+}
+
+template <size_t bufsz>
+void FormatBufferEx<bufsz>::prepare_buffer(bool is_append, const char * format, va_list argp) {
+  size_t len = jio_vsnprintf(NULL, 0, format, argp) + 1;
+  if (is_append) {
+    len += strlen(FormatBufferBase::_buf);
+  }
+  if (len > _buffer_size) {
+    _dyn_buffer = (_dyn_buffer == NULL) ? (char *)::malloc(len)
+                                        : (char *)::realloc(_dyn_buffer, len);
+    FormatBufferBase::_buf = _dyn_buffer;
+    _buffer_size = len;
+  }
+}
+
+template <size_t bufsz>
+void FormatBufferEx<bufsz>::printv(const char * format, va_list argp) {
+  va_list argp_local;
+  va_copy(argp_local, argp);
+  prepare_buffer(false, format, argp_local);
+  va_end(argp_local);
+
+  jio_vsnprintf(FormatBufferBase::_buf, _buffer_size, format, argp);
+}
+
+template <size_t bufsz>
+void FormatBufferEx<bufsz>::append(const char* format, ...) {
+  va_list argp, argp_prepare;
+  va_start(argp, format);
+  va_copy(argp_prepare, argp);
+  prepare_buffer(true, format, argp_prepare);
+  va_end(argp_prepare);
+
+  FormatBuffer<bufsz>::appendv(format, argp);
   va_end(argp);
 }
 
 // Used to format messages.
 typedef FormatBuffer<> err_msg;
< prev index next >