mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 12:32:43 +00:00 
			
		
		
		
	GIODevice: Add a read_all() that returns a ByteBuffer with all we can read.
Use this to implement file opening in TextEditor.
This commit is contained in:
		
							parent
							
								
									8e3d0a23d5
								
							
						
					
					
						commit
						9ad076178a
					
				
					 6 changed files with 58 additions and 25 deletions
				
			
		|  | @ -100,6 +100,7 @@ public: | |||
|     } | ||||
| 
 | ||||
|     ByteBuffer to_byte_buffer() const; | ||||
|     static String from_byte_buffer(const ByteBuffer&); | ||||
| 
 | ||||
|     static String format(const char*, ...); | ||||
| 
 | ||||
|  |  | |||
|  | @ -38,6 +38,7 @@ public: | |||
|     byte* offset_pointer(int offset) { return m_data + offset; } | ||||
|     const byte* offset_pointer(int offset) const { return m_data + offset; } | ||||
| 
 | ||||
|     void* end_pointer() { return m_data + m_size; } | ||||
|     const void* end_pointer() const { return m_data + m_size; } | ||||
| 
 | ||||
|     // NOTE: trim() does not reallocate.
 | ||||
|  | @ -109,6 +110,7 @@ public: | |||
|     byte* offset_pointer(ssize_t offset) { return m_impl ? m_impl->offset_pointer(offset) : nullptr; } | ||||
|     const byte* offset_pointer(ssize_t offset) const { return m_impl ? m_impl->offset_pointer(offset) : nullptr; } | ||||
| 
 | ||||
|     void* end_pointer() { return m_impl ? m_impl->end_pointer() : nullptr; } | ||||
|     const void* end_pointer() const { return m_impl ? m_impl->end_pointer() : nullptr; } | ||||
| 
 | ||||
|     // NOTE: trim() does not reallocate.
 | ||||
|  | @ -137,6 +139,13 @@ public: | |||
|             m_impl->grow(size); | ||||
|     } | ||||
| 
 | ||||
|     void append(const void* data, int data_size) | ||||
|     { | ||||
|         int old_size = size(); | ||||
|         grow(size() + data_size); | ||||
|         memcpy(pointer() + old_size, data, data_size); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     explicit ByteBuffer(RetainPtr<ByteBufferImpl>&& impl) | ||||
|         : m_impl(move(impl)) | ||||
|  |  | |||
|  | @ -92,6 +92,15 @@ ByteBuffer String::to_byte_buffer() const | |||
|     return ByteBuffer::copy(reinterpret_cast<const byte*>(characters()), length()); | ||||
| } | ||||
| 
 | ||||
| String String::from_byte_buffer(const ByteBuffer& buffer) | ||||
| { | ||||
|     if (buffer.is_null()) | ||||
|         return nullptr; | ||||
|     if (buffer.is_empty()) | ||||
|         return empty(); | ||||
|     return String((const char*)buffer.pointer(), buffer.size()); | ||||
| } | ||||
| 
 | ||||
| unsigned String::to_uint(bool& ok) const | ||||
| { | ||||
|     unsigned value = 0; | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ | |||
| #include <LibGUI/GTextEditor.h> | ||||
| #include <LibGUI/GAction.h> | ||||
| #include <LibGUI/GFontDatabase.h> | ||||
| #include <LibGUI/GFile.h> | ||||
| #include <AK/StringBuilder.h> | ||||
| #include <unistd.h> | ||||
| #include <stdio.h> | ||||
|  | @ -34,31 +35,13 @@ int main(int argc, char** argv) | |||
|     String path = "/tmp/TextEditor.save.txt"; | ||||
|     if (argc >= 2) { | ||||
|         path = argv[1]; | ||||
|         StringBuilder builder; | ||||
|         int fd = open(path.characters(), O_RDONLY); | ||||
|         if (fd < 0) { | ||||
|             perror("open"); | ||||
|         GFile file(path); | ||||
| 
 | ||||
|         if (!file.open(GIODevice::ReadOnly)) { | ||||
|             fprintf(stderr, "Opening %s: %s\n", path.characters(), file.error_string()); | ||||
|             return 1; | ||||
|         } | ||||
|         for (;;) { | ||||
|             char buffer[BUFSIZ]; | ||||
|             ssize_t nread = read(fd, buffer, sizeof(buffer)); | ||||
|             if (nread < 0) { | ||||
|                 perror("read"); | ||||
|                 return 1; | ||||
|             } | ||||
|             if (nread == 0) | ||||
|                 break; | ||||
|             builder.append(buffer, nread); | ||||
|         } | ||||
| 
 | ||||
|         int rc = close(fd); | ||||
|         if (rc < 0) { | ||||
|             perror("close"); | ||||
|             return 1; | ||||
|         } | ||||
| 
 | ||||
|         text_editor->set_text(builder.to_string()); | ||||
|         text_editor->set_text(String::from_byte_buffer(file.read_all())); | ||||
|     } | ||||
| 
 | ||||
|     auto new_action = GAction::create("New document", { Mod_Ctrl, Key_N }, GraphicsBitmap::load_from_file(GraphicsBitmap::Format::RGBA32, "/res/icons/16x16/new.rgb", { 16, 16 }), [] (const GAction&) { | ||||
|  |  | |||
|  | @ -46,7 +46,7 @@ ByteBuffer GIODevice::read(int max_size) | |||
|     return buffer; | ||||
| } | ||||
| 
 | ||||
| bool GIODevice::can_read() const | ||||
| bool GIODevice::can_read_from_fd() const | ||||
| { | ||||
|     // FIXME: Can we somehow remove this once GSocket is implemented using non-blocking sockets?
 | ||||
|     fd_set rfds; | ||||
|  | @ -68,12 +68,41 @@ bool GIODevice::can_read_line() | |||
|         return true; | ||||
|     if (m_buffered_data.contains_slow('\n')) | ||||
|         return true; | ||||
|     if (!can_read()) | ||||
|     if (!can_read_from_fd()) | ||||
|         return false; | ||||
|     populate_read_buffer(); | ||||
|     return m_buffered_data.contains_slow('\n'); | ||||
| } | ||||
| 
 | ||||
| bool GIODevice::can_read() const | ||||
| { | ||||
|     return !m_buffered_data.is_empty() || can_read_from_fd(); | ||||
| } | ||||
| 
 | ||||
| ByteBuffer GIODevice::read_all() | ||||
| { | ||||
|     ByteBuffer buffer; | ||||
|     if (!m_buffered_data.is_empty()) { | ||||
|         buffer = ByteBuffer::copy(m_buffered_data.data(), m_buffered_data.size()); | ||||
|         m_buffered_data.clear(); | ||||
|     } | ||||
| 
 | ||||
|     while (can_read_from_fd()) { | ||||
|         char read_buffer[4096]; | ||||
|         int nread = ::read(m_fd, read_buffer, sizeof(read_buffer)); | ||||
|         if (nread < 0) { | ||||
|             set_error(nread); | ||||
|             return buffer; | ||||
|         } | ||||
|         if (nread == 0) { | ||||
|             set_eof(true); | ||||
|             break; | ||||
|         } | ||||
|         buffer.append(read_buffer, nread); | ||||
|     } | ||||
|     return buffer; | ||||
| } | ||||
| 
 | ||||
| ByteBuffer GIODevice::read_line(int max_size) | ||||
| { | ||||
|     if (m_fd < 0) | ||||
|  |  | |||
|  | @ -28,6 +28,7 @@ public: | |||
| 
 | ||||
|     ByteBuffer read(int max_size); | ||||
|     ByteBuffer read_line(int max_size); | ||||
|     ByteBuffer read_all(); | ||||
| 
 | ||||
|     // FIXME: I would like this to be const but currently it needs to call populate_read_buffer().
 | ||||
|     bool can_read_line(); | ||||
|  | @ -49,6 +50,7 @@ protected: | |||
| 
 | ||||
| private: | ||||
|     bool populate_read_buffer(); | ||||
|     bool can_read_from_fd() const; | ||||
| 
 | ||||
|     int m_fd { -1 }; | ||||
|     int m_error { 0 }; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling