title: Reallocating/resizing Lua 5.1 userdata in C
body: <p>How do you resize a Lua 5.1 userdata object in C during runtime?</p>
  
  <p>I would like to change the size of the NumArray structure described in Roberto Ierusalimschy's book Programming in Lua, 2nd edition, pp. 260, from the Lua 5.1 console.</p>
  
  <p>My NumArray userdata can either store unsigned chars or lua_Numbers. I played around with calling the unmodified luaM_realloc_ function defined in lmem.c, but finally any call to C's realloc 
  (via l_alloc) function just returns NULL, so I get a <code>not enough memory</code> error message.</p>
  
  <p>Would somebody please help me ?</p>
  
  <pre><code>--- lapi.c -------------------------------------------------------------------------------------------------
  
  LUA_API void *agn_resizeud (lua_State *L, void *block, size_t osize, size_t nsize) {
    Udata *u = (Udata *)luaM_realloc_(L, block, osize + sizeof(Udata), nsize + sizeof(Udata));
    u-&gt;uv.len = nsize;
    if (u == NULL)
      luaL_error(L, "Error in " LUA_QS ": failed to allocate memory.", "API/agn_resizeud");
    return u;
  }
  
  --- numarray.c ---------------------------------------------------------------------------------------------
  
  #define checkarray(L, n) (NumArray *)luaL_checkudata(L, n, "numarray")
  
  [...]
  
  /* Auxiliary C function to finally call luaM_realloc_ via the Lua C API */
  
  void *reallocud (lua_State *L, void *block, size_t o, size_t n, size_t sizeofelem, size_t sizeofnumarray) {
    if (n + 1 &gt; MAX_SIZET/sizeofelem)
      luaL_error(L, "Error in " LUA_QS ": memory allocation error: block too big.", "(reallocud)", n);
    else
      return agn_resizeud(L, block, sizeofnumarray + o*sizeofelem, sizeofnumarray + n*sizeofelem);
  }
  
  /* function to resize a NumArray */
  
  static int numarray_resize (lua_State *L) {
    size_t i;
    global_State *g = G(L);
    NumArray *a = checkarray(L, 1);
    int n = luaL_checkinteger(L, 2);
    if (n &lt; 1)
      luaL_error(L, "Error in " LUA_QS ": new size %d is non-positive.", "numarray.resize", n);
    if (n == a-&gt;size) {   /* do nothing and do not complain */
      lua_pushinteger(L, a-&gt;size);
      return 1;
    }
    if (n &gt; a-&gt;size) {  /* extend */
      a = reallocud(L, a, a-&gt;size, n, a-&gt;isnumber ? sizeof(lua_Number) : sizeof(char), sizeof(NumArray));
      if (a-&gt;isnumber) {
        for (i=a-&gt;size; i &lt; n; i++) a-&gt;data.n[i] = 0;
      } else {
        for (i=a-&gt;size; i &lt; n; i++) a-&gt;data.c[i] = 0;
      }
    } else {  /* reduce */
      if (a-&gt;isnumber) {
        for (i=a-&gt;size - 1; i &gt; n - 1; i--) a-&gt;data.n[i] = 0;
      } else {
        for (i=a-&gt;size - 1; i &gt; n - 1; i--) a-&gt;data.c[i] = 0;
      }
      a = reallocud(L, a, a-&gt;size, n, a-&gt;isnumber ? sizeof(lua_Number) : sizeof(char), sizeof(NumArray));
    }
    a-&gt;size = n;
    lua_pushnumber(L, a-&gt;size);
    return 1;
  }
  
  [...]
  
  typedef struct NumArray {
    size_t size;           /* number of slots */
    char isnumber;
    union data {
      lua_Number n[1];  /* pointer to the various lua_Number values */
      unsigned char c[1];
    } data;
  } NumArray;
  </code></pre>