Browse Source

StringBuilder: Use a ByteBuffer internally instead of a Vector<String>.

Andreas Kling 6 years ago
parent
commit
9d7da26b4e
6 changed files with 58 additions and 37 deletions
  1. 14 0
      AK/Buffer.h
  2. 8 0
      AK/ByteBuffer.h
  3. 1 1
      AK/FileSystemPath.cpp
  4. 19 23
      AK/StringBuilder.cpp
  5. 5 2
      AK/StringBuilder.h
  6. 11 11
      Kernel/ProcFileSystem.cpp

+ 14 - 0
AK/Buffer.h

@@ -47,6 +47,8 @@ public:
         m_size = size;
     }
 
+    void grow(size_t size);
+
 private:
     enum ConstructionMode { Uninitialized, Copy, Wrap, Adopt };
     explicit Buffer(size_t); // For ConstructionMode=Uninitialized
@@ -87,7 +89,19 @@ inline Buffer<T>::Buffer(T* elements, size_t size, ConstructionMode mode)
     } else if (mode == Wrap) {
         m_owned = false;
     }
+}
 
+template<typename T>
+inline void Buffer<T>::grow(size_t size)
+{
+    ASSERT(size > m_size);
+    ASSERT(m_owned);
+    T* new_elements = static_cast<T*>(kmalloc(size * sizeof(T)));
+    memcpy(new_elements, m_elements, m_size * sizeof(T));
+    T* old_elements = m_elements;
+    m_elements = new_elements;
+    m_size = size;
+    kfree(old_elements);
 }
 
 template<typename T>

+ 8 - 0
AK/ByteBuffer.h

@@ -73,6 +73,14 @@ public:
         return copy(offset_pointer(offset), size);
     }
 
+    void grow(size_t size)
+    {
+        if (!m_impl)
+            m_impl = Buffer<byte>::create_uninitialized(size);
+        else
+            m_impl->grow(size);
+    }
+
 private:
     explicit ByteBuffer(RetainPtr<Buffer<byte>>&& impl)
         : m_impl(move(impl))

+ 1 - 1
AK/FileSystemPath.cpp

@@ -38,7 +38,7 @@ bool FileSystemPath::canonicalize(bool resolve_symbolic_links)
     StringBuilder builder;
     for (auto& cpart : canonical_parts) {
         builder.append('/');
-        builder.append(move(cpart));
+        builder.append(cpart);
     }
     m_string = builder.build();
     return true;

+ 19 - 23
AK/StringBuilder.cpp

@@ -1,22 +1,30 @@
 #include "StringBuilder.h"
 #include <LibC/stdarg.h>
 #include "printf.cpp"
+#include <AK/StdLibExtras.h>
 
 namespace AK {
 
-void StringBuilder::append(String&& str)
+inline void StringBuilder::will_append(size_t size)
 {
-    m_strings.append(move(str));
+    if ((m_length + size) > m_buffer.size())
+        m_buffer.grow(max(16u, m_buffer.size() * 2 + size));
 }
 
 void StringBuilder::append(const String& str)
 {
-    m_strings.append(str);
+    if (str.is_empty())
+        return;
+    will_append(str.length());
+    memcpy(m_buffer.pointer() + m_length, str.characters(), str.length());
+    m_length += str.length();
 }
 
 void StringBuilder::append(char ch)
 {
-    m_strings.append(StringImpl::create(&ch, 1));
+    will_append(1);
+    m_buffer.pointer()[m_length] = ch;
+    m_length += 1;
 }
 
 void StringBuilder::appendf(const char* fmt, ...)
@@ -29,27 +37,15 @@ void StringBuilder::appendf(const char* fmt, ...)
     va_end(ap);
 }
 
+ByteBuffer StringBuilder::to_byte_buffer()
+{
+    m_buffer.trim(m_length);
+    return m_buffer;
+}
+
 String StringBuilder::build()
 {
-    auto strings = move(m_strings);
-    if (strings.is_empty())
-        return String::empty();
-
-    size_t sizeNeeded = 0;
-    for (auto& string : strings)
-        sizeNeeded += string.length();
-
-    char* buffer;
-    auto impl = StringImpl::create_uninitialized(sizeNeeded, buffer);
-    if (!impl)
-        return String();
-
-    for (auto& string : strings) {
-        memcpy(buffer, string.characters(), string.length());
-        buffer += string.length();
-    }
-    *buffer = '\0';
-    return String(move(impl));
+    return String((const char*)m_buffer.pointer(), m_length);
 }
 
 }

+ 5 - 2
AK/StringBuilder.h

@@ -11,14 +11,17 @@ public:
     ~StringBuilder() { }
 
     void append(const String&);
-    void append(String&&);
     void append(char);
     void appendf(const char*, ...);
 
     String build();
+    ByteBuffer to_byte_buffer();
 
 private:
-    Vector<String> m_strings;
+    void will_append(size_t);
+
+    ByteBuffer m_buffer;
+    size_t m_length { 0 };
 };
 
 }

+ 11 - 11
Kernel/ProcFileSystem.cpp

@@ -42,7 +42,7 @@ ByteBuffer procfs$pid_fds(Process& process)
             continue;
         builder.appendf("% 3u %s\n", i, descriptor->absolute_path().characters());
     }
-    return builder.build().to_byte_buffer();
+    return builder.to_byte_buffer();
 }
 
 ByteBuffer procfs$pid_vm(Process& process)
@@ -58,7 +58,7 @@ ByteBuffer procfs$pid_vm(Process& process)
             region->committed(),
             region->name.characters());
     }
-    return builder.build().to_byte_buffer();
+    return builder.to_byte_buffer();
 }
 
 ByteBuffer procfs$pid_vmo(Process& process)
@@ -87,7 +87,7 @@ ByteBuffer procfs$pid_vmo(Process& process)
         }
         builder.appendf("\n");
     }
-    return builder.build().to_byte_buffer();
+    return builder.to_byte_buffer();
 }
 
 ByteBuffer procfs$pid_stack(Process& process)
@@ -111,7 +111,7 @@ ByteBuffer procfs$pid_stack(Process& process)
         unsigned offset = symbol.address - symbol.ksym->address;
         builder.appendf("%p  %s +%u\n", symbol.address, symbol.ksym->name, offset);
     }
-    return builder.build().to_byte_buffer();
+    return builder.to_byte_buffer();
 }
 
 ByteBuffer procfs$pid_regs(Process& process)
@@ -130,7 +130,7 @@ ByteBuffer procfs$pid_regs(Process& process)
     builder.appendf("flg: %x\n", tss.eflags);
     builder.appendf("sp:  %w:%x\n", tss.ss, tss.esp);
     builder.appendf("pc:  %w:%x\n", tss.cs, tss.eip);
-    return builder.build().to_byte_buffer();
+    return builder.to_byte_buffer();
 }
 
 ByteBuffer procfs$pid_exe(Process& process)
@@ -195,7 +195,7 @@ ByteBuffer procfs$mm()
     builder.appendf("VMO count: %u\n", MM.m_vmos.size());
     builder.appendf("Free physical pages: %u\n", MM.m_free_physical_pages.size());
     builder.appendf("Free supervisor physical pages: %u\n", MM.m_free_supervisor_physical_pages.size());
-    return builder.build().to_byte_buffer();
+    return builder.to_byte_buffer();
 }
 
 ByteBuffer procfs$mounts()
@@ -210,7 +210,7 @@ ByteBuffer procfs$mounts()
         else
             builder.appendf("%u:%u\n", mount.host().fsid(), mount.host().index());
     });
-    return builder.build().to_byte_buffer();
+    return builder.to_byte_buffer();
 }
 
 ByteBuffer procfs$cpuinfo()
@@ -273,7 +273,7 @@ ByteBuffer procfs$cpuinfo()
         copy_brand_string_part_to_buffer(2);
         builder.appendf("brandstr:  \"%s\"\n", buffer);
     }
-    return builder.build().to_byte_buffer();
+    return builder.to_byte_buffer();
 }
 
 ByteBuffer procfs$kmalloc()
@@ -287,7 +287,7 @@ ByteBuffer procfs$kmalloc()
         sum_alloc,
         sum_free
     );
-    return builder.build().to_byte_buffer();
+    return builder.to_byte_buffer();
 }
 
 ByteBuffer procfs$summary()
@@ -310,7 +310,7 @@ ByteBuffer procfs$summary()
             process->tty() ? strrchr(process->tty()->tty_name().characters(), '/') + 1 : "n/a",
             process->name().characters());
     }
-    return builder.build().to_byte_buffer();
+    return builder.to_byte_buffer();
 }
 
 ByteBuffer procfs$inodes()
@@ -323,7 +323,7 @@ ByteBuffer procfs$inodes()
         String path = vfs.absolute_path(*inode);
         builder.appendf("Inode{K%x} %02u:%08u (%u) %s\n", inode.ptr(), inode->fsid(), inode->index(), inode->retain_count(), path.characters());
     }
-    return builder.build().to_byte_buffer();
+    return builder.to_byte_buffer();
 }
 
 bool ProcFS::initialize()