Do not pad the final block of a file with zeroes.
[bluesky.git] / bluesky / util.c
index 1f98990..1f21bbf 100644 (file)
@@ -35,3 +35,71 @@ gchar *bluesky_lowercase(const gchar *s)
     /* TODO: Unicode handling; for now just do ASCII. */
     return g_ascii_strdown(s, -1);
 }
+
+/**** Reference-counted strings. ****/
+
+/* Create and return a new reference-counted string.  The reference count is
+ * initially one.  The newly-returned string takes ownership of the memory
+ * pointed at by data, and will call g_free on it when the reference count
+ * drops to zero. */
+BlueSkyRCStr *bluesky_string_new(gpointer data, gsize len)
+{
+    BlueSkyRCStr *string = g_new(BlueSkyRCStr, 1);
+    string->data = data;
+    string->len = len;
+    g_atomic_int_set(&string->refcount, 1);
+    return string;
+}
+
+void bluesky_string_ref(BlueSkyRCStr *string)
+{
+    if (string == NULL)
+        return;
+
+    g_atomic_int_inc(&string->refcount);
+}
+
+void bluesky_string_unref(BlueSkyRCStr *string)
+{
+    if (string == NULL)
+        return;
+
+    if (g_atomic_int_dec_and_test(&string->refcount)) {
+        g_free(string->data);
+        g_free(string);
+    }
+}
+
+/* Duplicate and return a new reference-counted string, containing a copy of
+ * the original data, with a reference count of 1.  As an optimization, if the
+ * passed-in string already has a reference count of 1, the original is
+ * returned.   Can be used to make a mutable copy of a shared string.  For this
+ * to truly be safe, it is probably needed that there be some type of lock
+ * protecting access to the string. */
+BlueSkyRCStr *bluesky_string_dup(BlueSkyRCStr *string)
+{
+    if (string == NULL)
+        return NULL;
+
+    if (g_atomic_int_dec_and_test(&string->refcount)) {
+        /* There are no other shared copies, so return this one. */
+        g_atomic_int_inc(&string->refcount);
+        return string;
+    } else {
+        return bluesky_string_new(g_memdup(string->data, string->len),
+                                  string->len);
+    }
+}
+
+/* Resize the data block used by a BlueSkyRCStr.  The data pointer might change
+ * after making this call, so it should not be cached across calls to this
+ * function.  To avoid confusing any other users, the caller probably ought to
+ * hold the only reference to the string (by calling bluesky_string_dup first
+ * if needed). */
+void bluesky_string_resize(BlueSkyRCStr *string, gsize len)
+{
+    if (string->len == len)
+        return;
+
+    string->data = g_realloc(string->data, len);
+}