{"thread":{"id":"36930","subject":"[PATCH 0/3] add strnncmp() function","startedAt":"2014-06-16T19:13:55Z","lastAt":"2014-06-17T07:13:32Z","messageCount":8,"participants":["Jeremiah Mahler","Jonathan Nieder"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"244333","messageId":"cover.1402945507.git.jmmahler@gmail.com","threadId":"36930","inReplyTo":null,"subject":"[PATCH 0/3] add strnncmp() function","fromName":"Jeremiah Mahler","fromEmail":"jmmahler@gmail.com","sentAt":"2014-06-16T19:13:55Z","receivedAt":"2014-06-16T19:13:55Z","isPatch":true,"sender":{"key":"jmmahler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/154028?v=4"},"body":"Add a strnncmp() function which behaves like strncmp() except it uses\nthe length of both strings instead of just one.\n\nThen simplify tree-walk.c and unpack-trees.c using this new function.\nReplace all occurances of name_compare() with strnncmp().  Remove\nname_compare(), which they both had identical copies of.\n\nJeremiah Mahler (3):\n  add strnncmp() function\n  tree-walk: simplify via strnncmp()\n  unpack-trees: simplify via strnncmp()\n\n strbuf.c       |  6 ++++++\n strbuf.h       |  2 ++\n tree-walk.c    | 16 +++-------------\n unpack-trees.c | 13 +------------\n 4 files changed, 12 insertions(+), 25 deletions(-)\n\n-- \n2.0.0\n"},{"id":"244334","messageId":"58e0ac866bdeb8cc6e06cf553a459af351ccfd1b.1402945507.git.jmmahler@gmail.com","threadId":"36930","inReplyTo":"cover.1402945507.git.jmmahler@gmail.com","subject":"[PATCH 1/3] add strnncmp() function","fromName":"Jeremiah Mahler","fromEmail":"jmmahler@gmail.com","sentAt":"2014-06-16T19:13:56Z","receivedAt":"2014-06-16T19:13:56Z","isPatch":true,"sender":{"key":"jmmahler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/154028?v=4"},"body":"Add a strnncmp() function which behaves like strncmp() except it uses\nthe length of both strings instead of just one.\n\nSigned-off-by: Jeremiah Mahler <jmmahler@gmail.com>\n---\n strbuf.c | 6 ++++++\n strbuf.h | 2 ++\n 2 files changed, 8 insertions(+)\n\ndiff --git a/strbuf.c b/strbuf.c\nindex ac62982..bd486c3 100644\n--- a/strbuf.c\n+++ b/strbuf.c\n@@ -600,3 +600,9 @@ char *xstrdup_tolower(const char *string)\n \tresult[i] = '\\0';\n \treturn result;\n }\n+\n+int strnncmp(const char *a, int len_a, const char *b, int len_b)\n+{\n+\tint min_len = (len_a < len_b) ? len_a : len_b;\n+\treturn (memcmp(a, b, min_len) || (len_a - len_b));\n+}\ndiff --git a/strbuf.h b/strbuf.h\nindex e9ad03e..88af9bf 100644\n--- a/strbuf.h\n+++ b/strbuf.h\n@@ -187,4 +187,6 @@ extern int fprintf_ln(FILE *fp, const char *fmt, ...);\n \n char *xstrdup_tolower(const char *);\n \n+extern int strnncmp(const char *a, int len_a, const char *b, int len_b);\n+\n #endif /* STRBUF_H */\n-- \n2.0.0\n"},{"id":"244335","messageId":"571d131f6ebeadb33999fe086656cb642710fb6f.1402945507.git.jmmahler@gmail.com","threadId":"36930","inReplyTo":"cover.1402945507.git.jmmahler@gmail.com","subject":"[PATCH 2/3] tree-walk: simplify via strnncmp()","fromName":"Jeremiah Mahler","fromEmail":"jmmahler@gmail.com","sentAt":"2014-06-16T19:13:57Z","receivedAt":"2014-06-16T19:13:57Z","isPatch":true,"sender":{"key":"jmmahler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/154028?v=4"},"body":"Simplify tree-walk.c using the strnncmp() function and remove the\nname_compare() function.\n\nSigned-off-by: Jeremiah Mahler <jmmahler@gmail.com>\n---\n tree-walk.c | 16 +++-------------\n 1 file changed, 3 insertions(+), 13 deletions(-)\n\ndiff --git a/tree-walk.c b/tree-walk.c\nindex 4dc86c7..efbd3b7 100644\n--- a/tree-walk.c\n+++ b/tree-walk.c\n@@ -144,16 +144,6 @@ struct tree_desc_x {\n \tstruct tree_desc_skip *skip;\n };\n \n-static int name_compare(const char *a, int a_len,\n-\t\t\tconst char *b, int b_len)\n-{\n-\tint len = (a_len < b_len) ? a_len : b_len;\n-\tint cmp = memcmp(a, b, len);\n-\tif (cmp)\n-\t\treturn cmp;\n-\treturn (a_len - b_len);\n-}\n-\n static int check_entry_match(const char *a, int a_len, const char *b, int b_len)\n {\n \t/*\n@@ -174,7 +164,7 @@ static int check_entry_match(const char *a, int a_len, const char *b, int b_len)\n \t * scanning further.\n \t */\n \n-\tint cmp = name_compare(a, a_len, b, b_len);\n+\tint cmp = strnncmp(a, a_len, b, b_len);\n \n \t/* Most common case first -- reading sync'd trees */\n \tif (!cmp)\n@@ -369,7 +359,7 @@ int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info)\n \t\t\t\tfirst_len = len;\n \t\t\t\tcontinue;\n \t\t\t}\n-\t\t\tif (name_compare(e->path, len, first, first_len) < 0) {\n+\t\t\tif (strnncmp(e->path, len, first, first_len) < 0) {\n \t\t\t\tfirst = e->path;\n \t\t\t\tfirst_len = len;\n \t\t\t}\n@@ -383,7 +373,7 @@ int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info)\n \t\t\t\tif (!e->path)\n \t\t\t\t\tcontinue;\n \t\t\t\tlen = tree_entry_len(e);\n-\t\t\t\tif (name_compare(e->path, len, first, first_len))\n+\t\t\t\tif (strnncmp(e->path, len, first, first_len))\n \t\t\t\t\tentry_clear(e);\n \t\t\t}\n \t\t}\n-- \n2.0.0\n"},{"id":"244336","messageId":"ee1716e209794a66eb9677e798164a356276700e.1402945507.git.jmmahler@gmail.com","threadId":"36930","inReplyTo":"cover.1402945507.git.jmmahler@gmail.com","subject":"[PATCH 3/3] unpack-trees: simplify via strnncmp()","fromName":"Jeremiah Mahler","fromEmail":"jmmahler@gmail.com","sentAt":"2014-06-16T19:13:58Z","receivedAt":"2014-06-16T19:13:58Z","isPatch":true,"sender":{"key":"jmmahler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/154028?v=4"},"body":"Simplify unpack-trees.c using the strnncmp() function and remove the\nname_compare() function.\n\nSigned-off-by: Jeremiah Mahler <jmmahler@gmail.com>\n---\n unpack-trees.c | 13 +------------\n 1 file changed, 1 insertion(+), 12 deletions(-)\n\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 4a9cdf2..9a71b5a 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -629,17 +629,6 @@ static int unpack_failed(struct unpack_trees_options *o, const char *message)\n \treturn -1;\n }\n \n-/* NEEDSWORK: give this a better name and share with tree-walk.c */\n-static int name_compare(const char *a, int a_len,\n-\t\t\tconst char *b, int b_len)\n-{\n-\tint len = (a_len < b_len) ? a_len : b_len;\n-\tint cmp = memcmp(a, b, len);\n-\tif (cmp)\n-\t\treturn cmp;\n-\treturn (a_len - b_len);\n-}\n-\n /*\n  * The tree traversal is looking at name p.  If we have a matching entry,\n  * return it.  If name p is a directory in the index, do not return\n@@ -678,7 +667,7 @@ static int find_cache_pos(struct traverse_info *info,\n \t\t\tce_len = ce_slash - ce_name;\n \t\telse\n \t\t\tce_len = ce_namelen(ce) - pfxlen;\n-\t\tcmp = name_compare(p->path, p_len, ce_name, ce_len);\n+\t\tcmp = strnncmp(p->path, p_len, ce_name, ce_len);\n \t\t/*\n \t\t * Exact match; if we have a directory we need to\n \t\t * delay returning it.\n-- \n2.0.0\n"},{"id":"244349","messageId":"20140616201644.GN8557@google.com","threadId":"36930","inReplyTo":"58e0ac866bdeb8cc6e06cf553a459af351ccfd1b.1402945507.git.jmmahler@gmail.com","subject":"Re: [PATCH 1/3] add strnncmp() function","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2014-06-16T20:16:44Z","receivedAt":"2014-06-16T20:16:44Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Jeremiah Mahler wrote:\n\n> Add a strnncmp() function which behaves like strncmp() except it uses\n> the length of both strings instead of just one.\n\nThe above description isn't very clear to me.  Problems:\n\n - strncmp compares prefixes of \\0-terminated strings.  This function\n   compares two binary buffers which can contain \\0\n\n - strncmp is a comparison function and can even be used with functions\n   like qsort (for operations like \"sort on the first two characters\").\n   This function returns 0 or nonzero.\n\nWould something like\n\n  /* true if buffers have the same length and are byte-for-byte identical */\n  int bufeq(const char *, int, const char *, int);\n\n(or buf_equal, array_equal etc) make sense?\n"},{"id":"244350","messageId":"20140616201806.GO8557@google.com","threadId":"36930","inReplyTo":"571d131f6ebeadb33999fe086656cb642710fb6f.1402945507.git.jmmahler@gmail.com","subject":"Re: [PATCH 2/3] tree-walk: simplify via strnncmp()","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2014-06-16T20:18:06Z","receivedAt":"2014-06-16T20:18:06Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Jeremiah Mahler wrote:\n\n> --- a/tree-walk.c\n> +++ b/tree-walk.c\n[...]\n> @@ -174,7 +164,7 @@ static int check_entry_match(const char *a, int a_len, const char *b, int b_len)\n>  \t * scanning further.\n>  \t */\n>  \n> -\tint cmp = name_compare(a, a_len, b, b_len);\n> +\tint cmp = strnncmp(a, a_len, b, b_len);\n\nThis changes behavior: the old version would only have 0 < cmp if\n'a' comes after 'b', while the new version always has 0 < cmp when\na != b.\n"},{"id":"244351","messageId":"20140616201905.GP8557@google.com","threadId":"36930","inReplyTo":"ee1716e209794a66eb9677e798164a356276700e.1402945507.git.jmmahler@gmail.com","subject":"Re: [PATCH 3/3] unpack-trees: simplify via strnncmp()","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2014-06-16T20:19:05Z","receivedAt":"2014-06-16T20:19:05Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Jeremiah Mahler wrote:\n\n> --- a/unpack-trees.c\n> +++ b/unpack-trees.c\n[...]\n> @@ -678,7 +667,7 @@ static int find_cache_pos(struct traverse_info *info,\n>  \t\t\tce_len = ce_slash - ce_name;\n>  \t\telse\n>  \t\t\tce_len = ce_namelen(ce) - pfxlen;\n> -\t\tcmp = name_compare(p->path, p_len, ce_name, ce_len);\n> +\t\tcmp = strnncmp(p->path, p_len, ce_name, ce_len);\n\nLikewise --- the sign of the result is important here.\n"},{"id":"244379","messageId":"20140617071332.GA3940@hudson.localdomain","threadId":"36930","inReplyTo":"20140616201806.GO8557@google.com","subject":"Re: [PATCH 2/3] tree-walk: simplify via strnncmp()","fromName":"Jeremiah Mahler","fromEmail":"jmmahler@gmail.com","sentAt":"2014-06-17T07:13:32Z","receivedAt":"2014-06-17T07:13:32Z","isPatch":true,"sender":{"key":"jmmahler@gmail.com","avatar":"https://avatars.githubusercontent.com/u/154028?v=4"},"body":"Jonathan,\n\nOn Mon, Jun 16, 2014 at 01:18:06PM -0700, Jonathan Nieder wrote:\n> Jeremiah Mahler wrote:\n> \n> > --- a/tree-walk.c\n> > +++ b/tree-walk.c\n> [...]\n> > @@ -174,7 +164,7 @@ static int check_entry_match(const char *a, int a_len, const char *b, int b_len)\n> >  \t * scanning further.\n> >  \t */\n> >  \n> > -\tint cmp = name_compare(a, a_len, b, b_len);\n> > +\tint cmp = strnncmp(a, a_len, b, b_len);\n> \n> This changes behavior: the old version would only have 0 < cmp if\n> 'a' comes after 'b', while the new version always has 0 < cmp when\n> a != b.\n\nThanks for catching this.  I did not realize that when I tried to\ncleanup the logic I inadvertently changed its behavior.\n\n    int strnncmp(const char *a, int len_a, const char *b, int len_b)\n    {\n           int min_len = (len_a < len_b) ? len_a : len_b;\n           return (memcmp(a, b, min_len) || (len_a - len_b));\n    }\n\nis not the same as:\n\n    static int name_compare(const char *a, int a_len,\n                           const char *b, int b_len)\n    {\n           int len = (a_len < b_len) ? a_len : b_len;\n           int cmp = memcmp(a, b, len);\n           if (cmp)\n                   return cmp;\n           return (a_len - b_len);\n    }\n\n(-5 || 3) is 1, not -5.\n\n-- \nJeremiah Mahler\njmmahler@gmail.com\nhttp://github.com/jmahler\n"}]}