From: Lars Schneider <larsxschnei...@gmail.com>

Sometimes pkt-line data is already available in a buffer and it would
be a waste of resources to write the packet using packet_write() which
would copy the existing buffer into a strbuf before writing it.

If the caller has control over the buffer creation then the
PKTLINE_DATA_START macro can be used to skip the header and write
directly into the data section of a pkt-line (PKTLINE_DATA_LEN bytes
would be the maximum). direct_packet_write() would take this buffer,
adjust the pkt-line header and write it.

If the caller has no control over the buffer creation then
direct_packet_write_data() can be used. This function creates a pkt-line
header. Afterwards the header and the data buffer are written using two
consecutive write calls.

Both functions have a gentle parameter that indicates if Git should die
in case of a write error (gentle set to 0) or return with a error (gentle
set to 1).

Signed-off-by: Lars Schneider <larsxschnei...@gmail.com>
---
 pkt-line.c | 42 ++++++++++++++++++++++++++++++++++++++++++
 pkt-line.h |  5 +++++
 2 files changed, 47 insertions(+)

diff --git a/pkt-line.c b/pkt-line.c
index 177dc73..aa158ba 100644
--- a/pkt-line.c
+++ b/pkt-line.c
@@ -136,6 +136,48 @@ void packet_write(int fd, const char *fmt, ...)
        write_or_die(fd, buf.buf, buf.len);
 }
 
+int direct_packet_write(int fd, char *buf, size_t size, int gentle)
+{
+       int ret = 0;
+       if (size > LARGE_PACKET_MAX) {
+               if (gentle)
+                       return 0;
+               else
+                       die("protocol error: impossibly long line");
+       }
+       packet_trace(buf + 4, size - 4, 1);
+       set_packet_header(buf, size);
+       if (gentle)
+               ret = !write_or_whine_pipe(fd, buf, size, "pkt-line");
+       else
+               write_or_die(fd, buf, size);
+       return ret;
+}
+
+int direct_packet_write_data(int fd, const char *data, size_t size, int gentle)
+{
+       int ret = 0;
+       char hdr[PKTLINE_HEADER_LEN];
+       if (size > PKTLINE_DATA_MAXLEN) {
+               if (gentle)
+                       return 0;
+               else
+                       die("protocol error: impossibly long line");
+       }
+       set_packet_header(hdr, PKTLINE_HEADER_LEN + size);
+       packet_trace(data, size, 1);
+       if (gentle) {
+               ret = (
+                       !write_or_whine_pipe(fd, hdr, PKTLINE_HEADER_LEN, 
"pkt-line header") ||
+                       !write_or_whine_pipe(fd, data, size, "pkt-line data")
+               );
+       } else {
+               write_or_die(fd, hdr, PKTLINE_HEADER_LEN);
+               write_or_die(fd, data, size);
+       }
+       return ret;
+}
+
 void packet_buf_write(struct strbuf *buf, const char *fmt, ...)
 {
        va_list args;
diff --git a/pkt-line.h b/pkt-line.h
index 3cb9d91..ed64511 100644
--- a/pkt-line.h
+++ b/pkt-line.h
@@ -23,6 +23,8 @@ void packet_flush(int fd);
 void packet_write(int fd, const char *fmt, ...) __attribute__((format (printf, 
2, 3)));
 void packet_buf_flush(struct strbuf *buf);
 void packet_buf_write(struct strbuf *buf, const char *fmt, ...) 
__attribute__((format (printf, 2, 3)));
+int direct_packet_write(int fd, char *buf, size_t size, int gentle);
+int direct_packet_write_data(int fd, const char *data, size_t size, int 
gentle);
 
 /*
  * Read a packetized line into the buffer, which must be at least size bytes
@@ -77,6 +79,9 @@ char *packet_read_line_buf(char **src_buf, size_t *src_len, 
int *size);
 
 #define DEFAULT_PACKET_MAX 1000
 #define LARGE_PACKET_MAX 65520
+#define PKTLINE_HEADER_LEN 4
+#define PKTLINE_DATA_START(pkt) ((pkt) + PKTLINE_HEADER_LEN)
+#define PKTLINE_DATA_MAXLEN (LARGE_PACKET_MAX - PKTLINE_HEADER_LEN)
 extern char packet_buffer[LARGE_PACKET_MAX];
 
 #endif
-- 
2.9.0

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to