llvm.org GIT mirror llvm / d4177b2
Modify raw_svector_ostream to use its SmallString without additional buffering. This is faster and avoids the stream and SmallString state synchronization issue. resync() is a no-op and may be safely deleted. I'll do so in a follow-up commit. Reviewed by Rafael Espindola. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@244870 91177308-0d34-0410-b5e6-96231b3b80d8 Yaron Keren 4 years ago
2 changed file(s) with 21 addition(s) and 84 deletion(s). Raw diff Collapse all Expand all
484484
485485 /// A raw_ostream that writes to an SmallVector or SmallString. This is a
486486 /// simple adaptor class. This class does not encounter output errors.
487 /// raw_svector_ostream operates without a buffer, delegating all memory
488 /// management to the SmallString. Thus the SmallString is always up-to-date,
489 /// may be used directly and there is no need to call flush().
487490 class raw_svector_ostream : public raw_pwrite_stream {
488491 SmallVectorImpl &OS;
489492
492495
493496 void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override;
494497
495 /// Return the current position within the stream, not counting the bytes
496 /// currently in the buffer.
498 /// Return the current position within the stream.
497499 uint64_t current_pos() const override;
498
499 protected:
500 // Like the regular constructor, but doesn't call init.
501 explicit raw_svector_ostream(SmallVectorImpl &O, unsigned);
502 void init();
503500
504501 public:
505502 /// Construct a new raw_svector_ostream.
506503 ///
507504 /// \param O The vector to write to; this should generally have at least 128
508505 /// bytes free to avoid any extraneous memory overhead.
509 explicit raw_svector_ostream(SmallVectorImpl &O);
510 ~raw_svector_ostream() override;
511
512 /// This is called when the SmallVector we're appending to is changed outside
513 /// of the raw_svector_ostream's control. It is only safe to do this if the
514 /// raw_svector_ostream has previously been flushed.
515 void resync();
516
517 /// Flushes the stream contents to the target vector and return a StringRef
518 /// for the vector contents.
519 StringRef str();
506 explicit raw_svector_ostream(SmallVectorImpl &O) : OS(O) {
507 SetUnbuffered();
508 }
509 ~raw_svector_ostream() override {}
510
511 // FIXME: resync is no-op. Remove it and its users.
512 void resync() {}
513
514 /// Return a StringRef for the vector contents.
515 StringRef str() { return StringRef(OS.data(), OS.size()); }
520516 };
521517
522518 /// A raw_ostream that discards all output.
539535 SmallVector Buffer;
540536
541537 public:
542 buffer_ostream(raw_ostream &OS) : raw_svector_ostream(Buffer, 0), OS(OS) {
543 init();
544 }
538 buffer_ostream(raw_ostream &OS) : raw_svector_ostream(Buffer), OS(OS) {}
545539 ~buffer_ostream() { OS << str(); }
546540 };
547541
754754 // raw_svector_ostream
755755 //===----------------------------------------------------------------------===//
756756
757 // The raw_svector_ostream implementation uses the SmallVector itself as the
758 // buffer for the raw_ostream. We guarantee that the raw_ostream buffer is
759 // always pointing past the end of the vector, but within the vector
760 // capacity. This allows raw_ostream to write directly into the correct place,
761 // and we only need to set the vector size when the data is flushed.
762
763 raw_svector_ostream::raw_svector_ostream(SmallVectorImpl &O, unsigned)
764 : OS(O) {}
765
766 raw_svector_ostream::raw_svector_ostream(SmallVectorImpl &O) : OS(O) {
767 init();
768 }
769
770 void raw_svector_ostream::init() {
771 // Set up the initial external buffer. We make sure that the buffer has at
772 // least 128 bytes free; raw_ostream itself only requires 64, but we want to
773 // make sure that we don't grow the buffer unnecessarily on destruction (when
774 // the data is flushed). See the FIXME below.
775 OS.reserve(OS.size() + 128);
776 SetBuffer(OS.end(), OS.capacity() - OS.size());
777 }
778
779 raw_svector_ostream::~raw_svector_ostream() {
780 // FIXME: Prevent resizing during this flush().
781 flush();
782 }
757 uint64_t raw_svector_ostream::current_pos() const { return OS.size(); }
758
759 void raw_svector_ostream::write_impl(const char *Ptr, size_t Size) {
760 OS.append(Ptr, Ptr + Size);
761 };
783762
784763 void raw_svector_ostream::pwrite_impl(const char *Ptr, size_t Size,
785764 uint64_t Offset) {
786 flush();
787 memcpy(OS.begin() + Offset, Ptr, Size);
788 }
789
790 /// resync - This is called when the SmallVector we're appending to is changed
791 /// outside of the raw_svector_ostream's control. It is only safe to do this
792 /// if the raw_svector_ostream has previously been flushed.
793 void raw_svector_ostream::resync() {
794 assert(GetNumBytesInBuffer() == 0 && "Didn't flush before mutating vector");
795
796 if (OS.capacity() - OS.size() < 64)
797 OS.reserve(OS.capacity() * 2);
798 SetBuffer(OS.end(), OS.capacity() - OS.size());
799 }
800
801 void raw_svector_ostream::write_impl(const char *Ptr, size_t Size) {
802 if (Ptr == OS.end()) {
803 // Grow the buffer to include the scratch area without copying.
804 size_t NewSize = OS.size() + Size;
805 assert(NewSize <= OS.capacity() && "Invalid write_impl() call!");
806 OS.set_size(NewSize);
807 } else {
808 assert(!GetNumBytesInBuffer());
809 OS.append(Ptr, Ptr + Size);
810 }
811
812 OS.reserve(OS.size() + 64);
813 SetBuffer(OS.end(), OS.capacity() - OS.size());
814 }
815
816 uint64_t raw_svector_ostream::current_pos() const {
817 return OS.size();
818 }
819
820 StringRef raw_svector_ostream::str() {
821 flush();
822 return StringRef(OS.begin(), OS.size());
765 memcpy(OS.data() + Offset, Ptr, Size);
823766 }
824767
825768 //===----------------------------------------------------------------------===//