On Thu, Aug 20, 2020 at 14:36:15 +0200, Michal Privoznik wrote:
On 8/20/20 1:02 PM, Peter Krempa wrote:
> On Tue, Jul 07, 2020 at 21:46:26 +0200, Michal Privoznik wrote:
> > This function will be used to detect zero buffers (which are
> > going to be interpreted as hole in virStream later).
> >
> > I shamelessly took inspiration from coreutils.
>
> Coreutils is proudly GPLv3 ...
>
Sure. But it was discussed in v1 and I think we agreed that the algorithm is
generic enough that it can be used in Libvirt too:
https://www.redhat.com/archives/libvir-list/2020-July/msg00170.html
> > Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
> > ---
> > src/libvirt_private.syms | 1 +
> > src/util/virstring.c | 38 ++++++++++++++++++++++++++++++++
> > src/util/virstring.h | 2 ++
> > tests/virstringtest.c | 47 ++++++++++++++++++++++++++++++++++++++++
> > 4 files changed, 88 insertions(+)
>
> [...]
>
> > diff --git a/src/util/virstring.c b/src/util/virstring.c
> > index e9e792f3bf..c26bc770d4 100644
> > --- a/src/util/virstring.c
> > +++ b/src/util/virstring.c
> > @@ -1404,3 +1404,41 @@ int virStringParseYesNo(const char *str, bool *result)
> > return 0;
> > }
> > +
> > +
> > +/**
> > + * virStringIsNull:
>
> IsNull might indicate that this does a check if the pointer is NULL. You
> are checking for NUL bytes.
Fair enough. I'm out of ideas though. Do you have a suggestion?
>
> > + * @buf: buffer to check
> > + * @len: the length of the buffer
> > + *
> > + * For given buffer @buf and its size @len determine whether
> > + * it contains only zero bytes (NUL) or not.
>
> Given the semantics of C strings being terminated by the NUL byte I
> don't think this function qualifies as a string helper and thus should
> probably reside somewhere outside of virstring.h
Alright. I will try to find better location. But since I want to use this
function from virsh too I'd like to have it in utils.
>
> > + *
> > + * Returns: true if buffer is full of zero bytes,
> > + * false otherwise.
> > + */
> > +bool virStringIsNull(const char *buf, size_t len)
> > +{
> > + const char *p = buf;
> > +
> > + if (!len)
> > + return true;
> > +
> > + /* Check up to 16 first bytes. */
> > + for (;;) {
> > + if (*p)
> > + return false;
> > +
> > + p++;
> > + len--;
> > +
> > + if (!len)
> > + return true;
> > +
> > + if ((len & 0xf) == 0)
> > + break;
> > + }
>
> Do we really need to do this optimization? We could arguably simplify
> this to:
>
> if (*buf != '\0')
> return false;
>
> return memcmp(buf, buf + 1, len - 1);
>
> You can then use the saved lines to explain that comparing a piece of
> memory with itself shifted by any position just ensures that there are
> repeating sequences of itself in the remainder and by shifting it by 1
> it means that it checks that the strings are just the same byte. The
> check above then ensuers that the one byte is NUL.
>
The idea is to pass aligned address to memcmp(). But I guess we can let
memcmp() deal with that.
Well, this explanation might justify the algorithm above, but it's
certainly not obvious, so please add a comment.