ucx/buffer.c

changeset 70
88092b88ec00
parent 17
11dffb40cd91
child 110
53895e9a4bbb
--- a/ucx/buffer.c	Fri Dec 12 15:48:54 2014 +0100
+++ b/ucx/buffer.c	Mon Dec 15 09:57:35 2014 +0100
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright 2013 Olaf Wintermann. All rights reserved.
+ * Copyright 2014 Olaf Wintermann. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -31,22 +31,22 @@
 #include <stdlib.h>
 #include <string.h>
 
-UcxBuffer *ucx_buffer_new(void *space, size_t size, int flags) {
+UcxBuffer *ucx_buffer_new(void *space, size_t capacity, int flags) {
     UcxBuffer *buffer = (UcxBuffer*) malloc(sizeof(UcxBuffer));
     if (buffer) {
         buffer->flags = flags;
         if (!space) {
-            buffer->space = (char*)malloc(size);
+            buffer->space = (char*)malloc(capacity);
             if (!buffer->space) {
                 free(buffer);
                 return NULL;
             }
-            memset(buffer->space, 0, size);
+            memset(buffer->space, 0, capacity);
             buffer->flags |= UCX_BUFFER_AUTOFREE;
         } else {
             buffer->space = (char*)space;
         }
-        buffer->capacity = size;
+        buffer->capacity = capacity;
         buffer->size = 0;
 
         buffer->pos = 0;
@@ -64,13 +64,8 @@
 
 UcxBuffer* ucx_buffer_extract(
         UcxBuffer *src, size_t start, size_t length, int flags) {
-    if(src->size == 0) {
-        return NULL;
-    }
-    if (length == 0) {
-        length = src->size - start;
-    }
-    if (start+length > src->size) {
+    
+    if (src->size == 0 || length == 0 || start+length > src->capacity) {
         return NULL;
     }
 
@@ -99,13 +94,21 @@
     case SEEK_END:
         npos = buffer->size;
         break;
+    case SEEK_SET:
+        npos = 0;
+        break;
     default:
-        npos = 0;
+        return -1;
     }
 
+    size_t opos = npos;
     npos += offset;
     
-    if (npos > buffer->size) {
+    if ((offset > 0 && npos < opos) || (offset < 0 && npos > opos)) {
+        return -1;
+    }
+    
+    if (npos >= buffer->size) {
         return -1;
     } else {
         buffer->pos = npos;
@@ -120,7 +123,17 @@
 
 int ucx_buffer_extend(UcxBuffer *buffer, size_t len) {
     size_t newcap = buffer->capacity;
-    while (buffer->pos + len > newcap) newcap <<= 1;
+    
+    if (buffer->capacity + len < buffer->capacity) {
+        return -1;
+    }
+    
+    while (buffer->capacity + len > newcap) {
+        newcap <<= 1;
+        if (newcap < buffer->capacity) {
+            return -1;
+        }
+    }
     
     char *newspace = (char*)realloc(buffer->space, newcap);
     if (newspace) {
@@ -137,18 +150,25 @@
 size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems,
         UcxBuffer *buffer) {
     size_t len = size * nitems;
-    if (buffer->pos + len > buffer->capacity) {
+    size_t required = buffer->pos + len;
+    if (buffer->pos > required) {
+        return 0;
+    }
+    
+    if (required > buffer->capacity) {
         if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) {
-            if(ucx_buffer_extend(buffer, len)) {
-                return -1;
+            if (ucx_buffer_extend(buffer, required - buffer->capacity)) {
+                return 0;
             }
         } else {
             len = buffer->capacity - buffer->pos;
-            if (size > 1) len -= len%size;
+            if (size > 1) {
+                len -= len%size;
+            }
         }
     }
     
-    if (len <= 0) {
+    if (len == 0) {
         return len;
     }
     

mercurial