#define _DEFAULT_SOURCE #include #include #include #include struct string_ro { size_t size; const void* data; }; struct string { union { struct string_ro ro; struct { size_t size; void* data; }; }; }; struct string_ro example; void something_that_stores_a_string(struct string_ro a){ const void* old = example.data; example.data = dpa_dupref_ro(a.data, a.size); dpa_put(old); } void something_using_it_later(void){ printf("example=\"%.*s\"\n", (int)example.size, (char*)example.data); } int main(){ struct string_ro s; s.size = 13; // A static string (TODO: Currently, dpa_dupref_ro unnecessarely copies it, because dpa_is_readonly doesn't know where the rodata is) { s.data = "Hello World!"; something_that_stores_a_string(s); } something_using_it_later(); // A string allocated with malloc, but not using dpa_malloc. It will be copied. { s.data = strdup("Hello World!"); something_that_stores_a_string(s); free((void*)s.data); } something_using_it_later(); // A string allocated with dpa_malloc, but not truely ro. It will be copied. { s.data = dpa_dup("Hello World!", 13); something_that_stores_a_string(s); dpa_put(s.data); } something_using_it_later(); // A string allocated with dpa_malloc and readonly. Only the refcount will increment. { s.data = dpa_readonly(dpa_dup("Hello World!", 13)); // dpa_dup_ro will currently also create a copy, but some day, that may be optimized away something_that_stores_a_string(s); dpa_put(s.data); } something_using_it_later(); // If we take a slice of our allocation, it will still only increment the refcount! { s.data = (char*)dpa_readonly(dpa_dup("Hello Sunny World!", 19)) + 6; something_that_stores_a_string(s); dpa_put(s.data); } something_using_it_later(); dpa_put(example.data); example.data = 0; example.size = 0; }