• Something like string-streams existing in "C"?

    From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Thu Dec 19 02:30:18 2024
    From Newsgroup: comp.lang.c

    Inspecting some of my "C" source code here I noticed a construct that
    I dislike...

    static char buf[32]; // sufficient space for ansi sequence
    ...
    sprintf (buf, "\033[38;5;%dm%c\033[0m", ...);

    In case of known or deducible string sizes I'm preferring and using
    some of the alloc() functions. In the sample I can at least deduce an upper-bound for the buffer-size. But it's anyway still an undesired
    hard-coded buffer size that I'd like to avoid.

    I recall that in C++ I used "String-Streams" for dynamically extended
    strings. But in "C" my reflex (and habit) is to write things like the
    above code.

    Is there something in "C" that allows dynamic flexibility of strings?
    (Or are there other options that an experienced "C" programmer would
    use instead?)

    (If there's something available only with newer C-standards I'd also
    appreciate a hint.)

    Janis
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Wed Dec 18 18:14:22 2024
    From Newsgroup: comp.lang.c

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    Inspecting some of my "C" source code here I noticed a construct that
    I dislike...

    static char buf[32]; // sufficient space for ansi sequence
    ...
    sprintf (buf, "\033[38;5;%dm%c\033[0m", ...);

    In case of known or deducible string sizes I'm preferring and using
    some of the alloc() functions. In the sample I can at least deduce an upper-bound for the buffer-size. But it's anyway still an undesired hard-coded buffer size that I'd like to avoid.

    I recall that in C++ I used "String-Streams" for dynamically extended strings. But in "C" my reflex (and habit) is to write things like the
    above code.

    Is there something in "C" that allows dynamic flexibility of strings?
    (Or are there other options that an experienced "C" programmer would
    use instead?)

    (If there's something available only with newer C-standards I'd also appreciate a hint.)

    You can use snprintf() for this. If the size argument is too small, it
    still returns the number of characters (excluding the terminating '\0')
    that would have been written to the buffer.

    char *buf;
    int arg1 = 42;
    int arg2 = 'x';
    int size = snprintf(buf, 0, "\033[38;5;%dm%c\033[0m", arg1, arg2);
    printf("Allocating %d bytes\n", size + 1);
    buf = malloc(size + 1); // error checking skipped
    int actual_size = snprintf(buf, size + 1, "\033[38;5;%dm%c\033[0m", arg1, arg2);
    printf("actual_size = %d, buf = \"%s\"\n", actual_size, buf);

    Note that the output includes non-printing characters, so you'll want to
    pipe it throught `cat -A` or something similar.

    Beware that the size argument includes the terminating null byte, but
    the value returned does not (it returns the length of the resulting
    string, not its size).

    GNU and BSD provide a non-standard asprintf() function that lets you do
    this in one step.
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Lawrence D'Oliveiro@ldo@nz.invalid to comp.lang.c on Thu Dec 19 04:41:25 2024
    From Newsgroup: comp.lang.c

    On Thu, 19 Dec 2024 02:30:18 +0100, Janis Papanagnou wrote:

    Is there something in "C" that allows dynamic flexibility of strings?

    As usual, standard C is pretty boring in this regard. And as usual, POSIX offers something a bit more.

    <https://manpages.debian.org/3/open_wmemstream.3.en.html>
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From BlueManedHawk@bluemanedhawk@invalid.invalid to comp.lang.c on Thu Dec 19 08:32:27 2024
    From Newsgroup: comp.lang.c

    The ‘asprintf’ subroutine is standardized by POSIX.1-2024, meaning that you can use it now and blame somebody else if it doesn't work. If you
    can't target POSIX, the subroutine is also _theoretically_ available
    through the feature-test macro ‘__STDC_WANT_LIB_EXT2__’, assuming that ‘__STDC_ALLOC_LIB__’ is a predefined macro, but gLibC does not pay attention to that for this subroutine, and which feature-test macro does induce its declaration is seemingly undocumented, though it is at least defined through ‘_DEFAULT_SOURCE’.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From scott@scott@slp53.sl.home (Scott Lurndal) to comp.lang.c on Thu Dec 19 13:53:21 2024
    From Newsgroup: comp.lang.c

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    Inspecting some of my "C" source code here I noticed a construct that
    I dislike...

    static char buf[32]; // sufficient space for ansi sequence
    ...
    sprintf (buf, "\033[38;5;%dm%c\033[0m", ...);

    snprintf is much safer for cases like this, as it will detect
    overflow and terminate the formatting before overrunning the buffer.

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Kaz Kylheku@643-408-1753@kylheku.com to comp.lang.c on Thu Dec 19 19:47:28 2024
    From Newsgroup: comp.lang.c

    On 2024-12-19, BlueManedHawk <bluemanedhawk@invalid.invalid> wrote:
    The ‘asprintf’ subroutine is standardized by POSIX.1-2024, meaning that you can use it now and blame somebody else if it doesn't work. If you

    Regardless of how it is made visible, you can detect it via a compile
    test in a configure script, and provide your own if it wasn't found:

    #if !HAVE_ASPRINTF

    int asprintf(char **out, const char *fmt, ...)
    {
    ... // more or less trivial to implement using malloc, realloc and
    vsprintf
    }

    #endif

    BTW, is there no wchar_t version of this?

    can't target POSIX, the subroutine is also _theoretically_ available
    through the feature-test macro ‘__STDC_WANT_LIB_EXT2__’, assuming that ‘__STDC_ALLOC_LIB__’ is a predefined macro, but gLibC does not pay

    When would it be the case that you can't target POSIX, but *can* mess
    around with some the internal feature test macros of some specific POSIX vendor? :)
    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Michael S@already5chosen@yahoo.com to comp.lang.c on Thu Dec 19 22:04:35 2024
    From Newsgroup: comp.lang.c

    On Thu, 19 Dec 2024 19:47:28 -0000 (UTC)
    Kaz Kylheku <643-408-1753@kylheku.com> wrote:
    On 2024-12-19, BlueManedHawk <bluemanedhawk@invalid.invalid> wrote:
    The ‘asprintf’ subroutine is standardized by POSIX.1-2024, meaning
    that you can use it now and blame somebody else if it doesn't work.
    If you

    Regardless of how it is made visible, you can detect it via a compile
    test in a configure script, and provide your own if it wasn't found:

    #if !HAVE_ASPRINTF

    int asprintf(char **out, const char *fmt, ...)
    {
    ... // more or less trivial to implement using malloc, realloc and
    vsprintf
    Don't you mean, vsnprintf ?
    }

    #endif

    BTW, is there no wchar_t version of this?

    can't target POSIX, the subroutine is also _theoretically_
    available through the feature-test macro ‘__STDC_WANT_LIB_EXT2__’, assuming that ‘__STDC_ALLOC_LIB__’ is a predefined macro, but gLibC does not pay

    When would it be the case that you can't target POSIX, but *can* mess
    around with some the internal feature test macros of some specific
    POSIX vendor? :)


    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Kaz Kylheku@643-408-1753@kylheku.com to comp.lang.c on Thu Dec 19 22:06:09 2024
    From Newsgroup: comp.lang.c

    On 2024-12-19, Michael S <already5chosen@yahoo.com> wrote:
    On Thu, 19 Dec 2024 19:47:28 -0000 (UTC)
    Kaz Kylheku <643-408-1753@kylheku.com> wrote:

    On 2024-12-19, BlueManedHawk <bluemanedhawk@invalid.invalid> wrote:
    The ‘asprintf’ subroutine is standardized by POSIX.1-2024, meaning
    that you can use it now and blame somebody else if it doesn't work.
    If you

    Regardless of how it is made visible, you can detect it via a compile
    test in a configure script, and provide your own if it wasn't found:

    #if !HAVE_ASPRINTF

    int asprintf(char **out, const char *fmt, ...)
    {
    ... // more or less trivial to implement using malloc, realloc and
    vsprintf

    Don't you mean, vsnprintf ?

    That detail will become obvious when you try to implement it.
    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Thiago Adams@thiago.adams@gmail.com to comp.lang.c on Thu Dec 19 23:14:17 2024
    From Newsgroup: comp.lang.c

    Em 12/19/2024 7:06 PM, Kaz Kylheku escreveu:
    On 2024-12-19, Michael S <already5chosen@yahoo.com> wrote:
    On Thu, 19 Dec 2024 19:47:28 -0000 (UTC)
    Kaz Kylheku <643-408-1753@kylheku.com> wrote:

    On 2024-12-19, BlueManedHawk <bluemanedhawk@invalid.invalid> wrote:
    The ‘asprintf’ subroutine is standardized by POSIX.1-2024, meaning >>>> that you can use it now and blame somebody else if it doesn't work.
    If you

    Regardless of how it is made visible, you can detect it via a compile
    test in a configure script, and provide your own if it wasn't found:

    #if !HAVE_ASPRINTF

    int asprintf(char **out, const char *fmt, ...)
    {
    ... // more or less trivial to implement using malloc, realloc and
    vsprintf

    Don't you mean, vsnprintf ?

    That detail will become obvious when you try to implement it.


    I did on implementation in 2020 (not using it)

    http://thradams.com/vadsprintf.html


    The standard should have a string stream compatible with FILE because
    - differently of asprintf - if cannot be implemented separately.


    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Fri Dec 20 03:56:34 2024
    From Newsgroup: comp.lang.c

    On 19.12.2024 02:30, Janis Papanagnou wrote:
    [...]

    Thanks for the various suggestions and hints. I've got an idea
    what's possible and what I'll buy with each option. That's very
    useful information.

    Janis

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Michael S@already5chosen@yahoo.com to comp.lang.c on Fri Dec 20 12:38:40 2024
    From Newsgroup: comp.lang.c

    On Thu, 19 Dec 2024 22:06:09 -0000 (UTC)
    Kaz Kylheku <643-408-1753@kylheku.com> wrote:
    On 2024-12-19, Michael S <already5chosen@yahoo.com> wrote:
    On Thu, 19 Dec 2024 19:47:28 -0000 (UTC)
    Kaz Kylheku <643-408-1753@kylheku.com> wrote:

    On 2024-12-19, BlueManedHawk <bluemanedhawk@invalid.invalid>
    wrote:
    The ‘asprintf’ subroutine is standardized by POSIX.1-2024,
    meaning that you can use it now and blame somebody else if it
    doesn't work. If you

    Regardless of how it is made visible, you can detect it via a
    compile test in a configure script, and provide your own if it
    wasn't found:

    #if !HAVE_ASPRINTF

    int asprintf(char **out, const char *fmt, ...)
    {
    ... // more or less trivial to implement using malloc, realloc
    and vsprintf

    Don't you mean, vsnprintf ?

    That detail will become obvious when you try to implement it.

    It sounds like Janis would prefer different API.
    struct string_buffer {
    char* ptr;
    size_t len;
    size_t cap;
    };
    int append_printf(struct string_buffer*, , const char *fmt, ...); Implementation is as trivial as asprintf.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Michael S@already5chosen@yahoo.com to comp.lang.c on Fri Dec 20 13:00:56 2024
    From Newsgroup: comp.lang.c

    On Thu, 19 Dec 2024 23:14:17 -0300
    Thiago Adams <thiago.adams@gmail.com> wrote:
    Em 12/19/2024 7:06 PM, Kaz Kylheku escreveu:
    On 2024-12-19, Michael S <already5chosen@yahoo.com> wrote:
    On Thu, 19 Dec 2024 19:47:28 -0000 (UTC)
    Kaz Kylheku <643-408-1753@kylheku.com> wrote:

    On 2024-12-19, BlueManedHawk <bluemanedhawk@invalid.invalid>
    wrote:
    The ‘asprintf’ subroutine is standardized by POSIX.1-2024,
    meaning that you can use it now and blame somebody else if it
    doesn't work. If you

    Regardless of how it is made visible, you can detect it via a
    compile test in a configure script, and provide your own if it
    wasn't found:

    #if !HAVE_ASPRINTF

    int asprintf(char **out, const char *fmt, ...)
    {
    ... // more or less trivial to implement using malloc, realloc
    and vsprintf

    Don't you mean, vsnprintf ?

    That detail will become obvious when you try to implement it.


    I did on implementation in 2020 (not using it)

    http://thradams.com/vadsprintf.html

    You mean, you don't use asprintf() that you implemented?
    That's understandable. The API is rather badly designed. Can be handy
    in toy examples, less so in production software.

    The standard should have a string stream compatible with FILE because
    - differently of asprintf - if cannot be implemented separately.

    What level of compatibility?
    IMHO, the level that makes sense is where compatibility excludes
    fopen, fclose and fflush. I.e. you have new functions, mem_fopen()
    and mem_fclose() and do not allow fflush(). Pluse, you add few more
    functions or macros for direct access to buffer.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Thiago Adams@thiago.adams@gmail.com to comp.lang.c on Fri Dec 20 08:32:24 2024
    From Newsgroup: comp.lang.c

    Em 12/20/2024 8:00 AM, Michael S escreveu:
    On Thu, 19 Dec 2024 23:14:17 -0300
    Thiago Adams <thiago.adams@gmail.com> wrote:

    Em 12/19/2024 7:06 PM, Kaz Kylheku escreveu:
    On 2024-12-19, Michael S <already5chosen@yahoo.com> wrote:
    On Thu, 19 Dec 2024 19:47:28 -0000 (UTC)
    Kaz Kylheku <643-408-1753@kylheku.com> wrote:

    On 2024-12-19, BlueManedHawk <bluemanedhawk@invalid.invalid>
    wrote:
    The ‘asprintf’ subroutine is standardized by POSIX.1-2024,
    meaning that you can use it now and blame somebody else if it
    doesn't work. If you

    Regardless of how it is made visible, you can detect it via a
    compile test in a configure script, and provide your own if it
    wasn't found:

    #if !HAVE_ASPRINTF

    int asprintf(char **out, const char *fmt, ...)
    {
    ... // more or less trivial to implement using malloc, realloc
    and vsprintf

    Don't you mean, vsnprintf ?

    That detail will become obvious when you try to implement it.


    I did on implementation in 2020 (not using it)

    http://thradams.com/vadsprintf.html


    You mean, you don't use asprintf() that you implemented?
    That's understandable. The API is rather badly designed. Can be handy
    in toy examples, less so in production software.


    For my needs a string stream is better I am using this https://github.com/thradams/cake/blob/main/src/osstream.c
    Unfortunately it is not compatible with FILE*.



    The standard should have a string stream compatible with FILE because
    - differently of asprintf - if cannot be implemented separately.


    What level of compatibility?
    IMHO, the level that makes sense is where compatibility excludes
    fopen, fclose and fflush. I.e. you have new functions, mem_fopen()
    and mem_fclose() and do not allow fflush(). Pluse, you add few more
    functions or macros for direct access to buffer.



    A function printing in a FILE* fprint also should be able to print in a
    string stream.


    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Michael S@already5chosen@yahoo.com to comp.lang.c on Fri Dec 20 14:55:41 2024
    From Newsgroup: comp.lang.c

    On Fri, 20 Dec 2024 08:32:24 -0300
    Thiago Adams <thiago.adams@gmail.com> wrote:

    A function printing in a FILE* fprint also should be able to print in
    a string stream.


    Of course.
    But I don't like your naming and semantics implied by the name.
    It should be memory buffer stream rather than string stream.
    I.e. zero characters should be allowed in the middle, zero termination
    not guaranteed, fwrite and fputc should work as expected etc...


    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Fri Dec 20 10:45:01 2024
    From Newsgroup: comp.lang.c

    Michael S <already5chosen@yahoo.com> writes:
    On Thu, 19 Dec 2024 23:14:17 -0300
    Thiago Adams <thiago.adams@gmail.com> wrote:
    [...]
    The standard should have a string stream compatible with FILE because
    - differently of asprintf - if cannot be implemented separately.

    What level of compatibility?
    IMHO, the level that makes sense is where compatibility excludes
    fopen, fclose and fflush. I.e. you have new functions, mem_fopen()
    and mem_fclose() and do not allow fflush(). Pluse, you add few more
    functions or macros for direct access to buffer.

    POSIX defines fmemopen(), similar to fopen().

    FILE *fmemopen(void *restrict buf, size_t max_size, const char *restrict mode); --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Lawrence D'Oliveiro@ldo@nz.invalid to comp.lang.c on Fri Dec 20 20:39:12 2024
    From Newsgroup: comp.lang.c

    On Fri, 20 Dec 2024 08:32:24 -0300, Thiago Adams wrote:

    For my needs a string stream is better I am using this https://github.com/thradams/cake/blob/main/src/osstream.c Unfortunately
    it is not compatible with FILE*.

    As usual, standard C is pretty boring in this regard. And as usual, POSIX offers something a bit more.

    <https://manpages.debian.org/3/open_wmemstream.3.en.html>
    --- Synchronet 3.20a-Linux NewsLink 1.114