-2

I was reading the source code of the Lua programming language lately and found some of the conventions unclear or confusing. For example, the str_reverse function in this file. Is it considered as clean code and understandable code in C ?

static int str_reverse (lua_State *L) {
   size_t l, i;
   luaL_Buffer b;
   const char *s = luaL_checklstring(L, 1, &l);
   char *p = luaL_buffinitsize(L, &b, l);
   for (i = 0; i < l; i++)
       p[i] = s[l - i - 1];
   luaL_pushresultsize(&b, l);
   return 1;
}

In these lines:

char *p = luaL_buffinitsize(L, &b, l);
for (i = 0; i < l; i++)
   p[i] = s[l - i - 1];

*p is created to store the value of string after being reversed. After that, i don't see it is used anywhere else. Then looking into char *p = luaL_buffinitsize(L, &b, l);, it shows that *p is a property of luaL_Buffer b;, which is now making sense why *p is not used anymore, because in the next line, b is in use

Also, in this line const char *s = luaL_checklstring(L, 1, &l);, this luaL_checklstring function return *s, but also, assign length of string(got from L) to size_t l variable. So this function not only return 1 variable and but also change 1 variable along its way.

Trieu Nguyen
  • 933
  • 1
  • 11
  • 17
  • 2
    That code seems fine to me. This question seems rather opinion-based too. – Retired Ninja Nov 28 '18 at 04:56
  • 1
    It's pretty normal and understandable C code, but it takes a while to learn how it works. I recently taught myself C. Actually, asterisks are not part of variable names; `char *` means "pointer to char" and the variable `p` is used in the line `p[i] = s[l - i - 1];`. – cyclaminist Nov 28 '18 at 05:46
  • C does not allow functions to directly return multiple values the way Lua does (`function () return 1, 2 end`), so when a function needs to return multiple values, pointers are often used. Because `checklstring` needs to return two values, a string and the length of the string, it uses a pointer, the third argument (`&l`). See [this question](https://stackoverflow.com/questions/3829167/returning-multiple-values-from-a-function). – cyclaminist Nov 28 '18 at 05:59

1 Answers1

3

When you don't know how something works, it's a reasonable conclusion that it may be written poorly. However, the code above is readable. I don't know anything about lua and not that much about C and I'm able to decipher what's going on.

The first thing that might help you is to understand how str_reverse is called, fire up an interpreter:

> str = "foo"         /* create a string in a lua state */
> string.reverse(str) /* indirectly invokes str_reverse */
oof                   /* result */

The first thing str_reverse does is call luaL_checklstring, which is a wrapper function around lua_tolstring that adds error checking. In dialog:

str_reverse says to luaL_checklstring:

"Hey, I need a string - give me the address (stores it in s), also I need the length (stores it in l)."

luaL_checklstring says: "yep, all is good - here ya go!"

You see, the C language needs to know the size of everything so it can allocate the proper amount of memory. Since str_reverse needs to allocate memory for the reversed string (more precisely, luaL_Buffer b will need to be resized if it's not large enough to accommodate the string), it tells luaL_checklstring to give the length as well. If str_reverse didn't care about the length NULL would be passed instead of l. This is how the Lua API is designed - seems readable to me.

p doesn't store the value of the string - the reversed string is stored in b, as a member. p is basically a shortcut, consider the following:

/* disregard the pointer returned by buffinitsize */
luaL_buffinitsize(L, &b, l);
for (i = 0; i < l; i++)
    b->b[i] = s[l - i - 1];

The above code should work the same. Except now, the gory details of the luaL_Buffer are exposed...not great.

You need to read up on pointers. You'll never fully understand C if you don't understand pointers, it'd be like walking with no feet.

Anyway, It sucks you're being down-voted so much, it's probably the title you chose for your question - it sounds like you're bashing Lua. Aside from that, your question seems genuine - good luck and have fun in your adventures of reading other people's code!

fbynite
  • 2,651
  • 1
  • 21
  • 25
  • Hi, thanks for your help, it answer my question. Can you help me understand the lua_State *L ?, i don't know how it is created and why it stores so many things inside it, it seems to store parameter for the function as well. – Trieu Nguyen Nov 29 '18 at 03:08
  • 1
    When you call Lua from the command line, `lua_State` is created by the `lua` binary. Check out the [this answer](https://stackoverflow.com/a/4201531/722238) for [What is a Lua State?](https://stackoverflow.com/q/4201284/722238). – fbynite Nov 29 '18 at 08:38