Proposal for a full-fledged C String

12 points by alcover ↗ HN
Dynamic allocation, SSO, views, refcounting, etc.. are spread on various implementations.

C++ separates string and string_view. And they're not fully compatible. (Ex. you can't concat cross-type !?).

Rust has str, &str, String Box<str>, ... ?

In the spirit of "a slice of a string is still a string", why not pack it all into a single type ? And offer security in the process.

Here's the scheme : https://github.com/alcover/buffet/raw/main/assets/schema.png

Here's the code : https://github.com/alcover/buffet

NB: I'm talking string/byte buffer. Higher string tooling like Utf8 would go a layer above.

13 comments

[ 3.0 ms ] story [ 43.3 ms ] thread
interesting idea, I had a few questions when looking at it

- afaik size_t and char* types are implementation dependent, not sure if this could cause problems, maybe you already thought about the implications?

- are you hard set on using GPL?

No prob with size_t and char* I think. They'll nicely solidify to 4 bytes on 32-bit platforms. I'd need to test for maximum though in size_t .len case.

GPL : Not really. Maybe LGPL would do. I want the lib to promote open source and that's it.

> No prob with size_t and char* I think. They'll nicely solidify to 4 bytes on 32-bit platforms. I'd need to test for maximum though in size_t .len case.

I mean on 32 bit platform the offset to union tag would be different depending on the struct the union holds, unless I'm missing something

The hard values in the readme may be confusing. The real model is

  union {
      struct {
          char*   data;
          size_t  len;
          size_t  off:8*sizeof(size_t)-TAGBITS, tag:TAGBITS;
      } ptr;
  
      struct {
          char    data[sizeof(BuffetPtr)-2];
          uint8_t refcnt;
          uint8_t len:8-TAGBITS, tag:TAGBITS;
      } sso;
  }
where the tag falls into place. I tried an older version on 32 bit and it worked ok.
ahhh thanks, now that makes more sense to me
MIT might be a better license for broad adoption. Both GPL and LGPL are viral licenses. They serve a purpose, but you need to assess if that purpose is the same as yours.
Would you object to MIT now and GPL/dual later when mature ? Though I suppose the license doesn't count when people are just trying the lib (which they seemingly don't..)
If it were dual-licensed, I think it’d be hard to find anyone who’d object. GPL is scary to me, though, since I prefer to license my stuff under pretty unrestrictive licenses, and I don’t really want to deal with the virality.
exactly my thoughts, generally GPL any version or (L)GPLv3 or greater means your library will never be included in a commercial product, hence crippling the mass adaption
we had this optimized string before here. I really wanted to try it out in a compiler or runtime, but hadn't had the time yet. anyone else already tried it?

  > anyone else already tried it?
That's what I wonder too... working on this without any return other than lots of github stars is a bit discouraging.
I think the model that Free Pascal uses could be adapted to C. It's a reference counted, counted string of bytes. The pointer to the string actually points past the allocation, reference count, length, etc.. at the first byte of the string. There is a \0 added on the end for safety when passing to OS calls.

Code to modify the string does a copy, decrement the ref count of the original, and then modify of the new string.

Copies of a string are essentially free. You can return them from functions, etc. with no worry about allocation. The run-time handles all of that.

In C, there are mechanisms for running macros when a variable goes out of scope, those could be used to decrement the reference counter to a string used locally inside a function. (Returning the string would need to increase it's ref count first, of course)

(comment deleted)