Re: [PATCH v14 09/27] bisect--helper: `bisect_write` shell function in C

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hey Junio,

On Sun, Aug 28, 2016 at 2:52 AM, Junio C Hamano <gitster@xxxxxxxxx> wrote:
>
> Pranit Bauva <pranit.bauva@xxxxxxxxx> writes:
>
> >>> +struct bisect_terms {
> >>> +     struct strbuf term_good;
> >>> +     struct strbuf term_bad;
> >>> +};
> >>
> >> I think "struct strbuf" is overrated.  ...
> >> I think you can just say "const char *" in this case.
> >
> > Using struct strbuf is not really overrated but in fact required. But
>
> Nothing is required.
>
> I can make your life easier by requiring you to never use struct
> strbuf as a structure field type, though.  You will almost never
> need it unless you are building something exotic anyway.
>
> Step back and think what "strbuf" is good for.  It holds a pointer
> to a piece of memory the field owns, over-allocates and knows the
> size of allocation and usage.  That is good if you need to
>
>  (1) frequently find out the length of the string; without a
>      separate .len member you would have to run strlen().
>
>  (2) incrementally add to the string in-place; as it overallocates,
>      appending to the string would not have to involve realloc()
>      every time and the cost of it is amortized.
>
>  (3) make complex operations like splicing another string in,
>      trimming substring out, etc.
>
> You need to do none of the above to these fields.  term.term_good is
> either taken from an argv[] element, or you read from a line from a
> file and set it.  You may do some trivial computation and set it to
> the result, like "the other field uses 'old', so this one need to be
> set to 'new'".  The user of the field either has the string and sets
> it there, or reads the field's value as a whole string.  No string
> manipulation in the field in-place is needed.
>
> > yes, for this patch it might seem as overrated. In the shell code
> > initally TERM_GOOD is set to "good" while TERM_BAD is set to "bad".
> > Now there are a lot of instances (one of which is bisect_start()
> > function) where this can change. So if we keep it as "const char *",
> > it would be right to change the value of it after wards. And we cannot
> > keep it as "char []" because we don't know its size before hand.
>
> You are not making sense.  Nobody would suggest to use a fixed-size
> char array in this structure.  That wouldn't even work in the case
> where you are stuffing what comes in an argv[] element in there,
> e.g.
>
>     terms.term_good = argv[3];
>
> And you can of course support changing the value of the field
> without using strbuf.  Just update the pointer to point at the piece
> of memory that holds the new value.
>
> In short, I do not see any good reason why the term_good field has
> to be anything other than "char *term_good" or "const char *term_good".
>
> Now, what you need to consider choosing between the two depends on
> where these strings can come from.  If they are known to be always
> unchanging between the time you set it til the end of the program
> (e.g. using an element in argv[]), you can just assign without
> making any copy and you can use "const char *term_good".  All other
> cases, the structure needs to take the ownership, and you would need
> to make a copy if you don't have the ownership, e.g.
>
>         terms.term_good = xstrdup(argv[3]);
>
> You may be reading from a file, a line at a time and you may have a
> line's content in a strbuf.  You do not (yet) own the buffer after
> reading it, e.g.
>
>         strbuf_getline(&buf, fp);
>         terms.term_good = strbuf_detach(&buf, NULL);
>
> Of course, if you need to take ownership of the memory, you would
> need to free(3) it as needed, which means the pattern to set the
> field would become
>
>         free(terms.term_good);
>         terms.term_good = ... some new value ...;
>
> Using strbuf as a local variable is good.  It gives a higher level
> of abstraction when you are actually performing string operations.
> In most applications, however, a field in a struct is where the
> result of a step of computation is kept, not a scratch-pad to
> perform steps of computation in.  When you are ready to update the
> value of a field, you _have_ a completed string, and you can just
> use "char *" field to point at it.  There is no need for strbuf in
> the field.
>
> Don't look at the data structure used in trailer.[ch] as a model; it
> is an example of a terribly bad implementation taste, a pattern that
> should not be followed.  Print it, not read it and burn it as a good
> symbolic gesture.

Thanks for explaining when to use strbuf. I am convinced that the
thing I am aiming for can be done with the help of "const char *".
Though I will have to use strbuf in get_terms() and detach the string
buffer from there as you have mentioned previously.

Regards,
Pranit Bauva



[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]