Example #1
0
File: marshal.c Project: ntd/lgi
/* Creates or marshalls content of GIArgument to/from lua according to
   specified typeinfo.
   arg, ptr = marshal.argument()
   value = marshal.argument(arg, typeinfo, transfer)
   marshal.argument(arg, typeinfo, transfer, value) */
static int
marshal_argument (lua_State *L)
{
  GITypeInfo **info;
  GITransfer transfer;
  GIArgument *arg;

  if (lua_isnone (L, 1))
    {
      /* Create new argument userdata. */
      GIArgument *arg = lua_newuserdata (L, sizeof (*arg));
      memset (arg, 0, sizeof (*arg));
      lua_pushlightuserdata (L, arg);
      return 2;
    }

  arg = lua_touserdata (L, 1);
  info = luaL_checkudata (L, 2, LGI_GI_INFO);
  transfer = luaL_checkoption (L, 3, transfers[0], transfers);
  if (lua_isnone (L, 4))
    {
      lgi_marshal_2lua (L, *info, NULL, GI_DIRECTION_IN, transfer, arg,
			0, NULL, NULL);
      return 1;
    }
  else
    {
      lua_pop (L, lgi_marshal_2c (L, *info, NULL, transfer, arg, 4,
				  0, NULL, NULL));
      return 0;
    }
}
Example #2
0
File: core.c Project: TDKPS/lgi
/* Instantiate constant from given gi_info. */
static int
core_constant (lua_State *L)
{
  /* Get typeinfo of the constant. */
  GIArgument val;
  GIConstantInfo *ci = *(GIConstantInfo **) luaL_checkudata (L, 1, LGI_GI_INFO);
  GITypeInfo *ti = g_constant_info_get_type (ci);
  lgi_gi_info_new (L, ti);
  g_constant_info_get_value (ci, &val);
  lgi_marshal_2lua (L, ti, GI_TRANSFER_NOTHING, &val, 0, NULL, NULL);
  return 1;
}
Example #3
0
File: marshal.c Project: ntd/lgi
static void
marshal_2lua_hash (lua_State *L, GITypeInfo *ti, GIDirection dir,
		   GITransfer xfer, GHashTable *hash_table)
{
  GHashTableIter iter;
  GITypeInfo *eti[2];
  gint i, guard;
  GIArgument eval[2];

  /* Check for 'NULL' table, represent it simply as nil. */
  if (hash_table == NULL)
    lua_pushnil (L);
  else
    {
      /* Get key and value type infos, guard them so that we don't
	 leak it. */
      guard = lua_gettop (L) + 1;
      for (i = 0; i < 2; i++)
	{
	  eti[i] = g_type_info_get_param_type (ti, i);
	  lgi_gi_info_new (L, eti[i]);
	}

      /* Create table to which we will deserialize the hashtable. */
      lua_newtable (L);

      /* Go through the hashtable and push elements into the table. */
      g_hash_table_iter_init (&iter, hash_table);
      while (g_hash_table_iter_next (&iter, &eval[0].v_pointer,
				     &eval[1].v_pointer))
	{
	  /* Marshal key and value to the stack. */
	  for (i = 0; i < 2; i++)
	    lgi_marshal_2lua (L, eti[i], NULL, dir, GI_TRANSFER_NOTHING,
			      &eval[i], LGI_PARENT_FORCE_POINTER, NULL, NULL);

	  /* Store these two elements to the table. */
	  lua_settable (L, -3);
	}

      /* Free the table, if requested. */
      if (xfer != GI_TRANSFER_NOTHING)
	g_hash_table_unref (hash_table);

      lua_remove (L, guard);
      lua_remove (L, guard);
    }
}
Example #4
0
File: marshal.c Project: ntd/lgi
static int
marshal_2lua_list (lua_State *L, GITypeInfo *ti, GIDirection dir,
		   GITypeTag list_tag, GITransfer xfer, gpointer list)
{
  GSList *i;
  GITypeInfo *eti;
  gint index, eti_guard;

  /* Get element type info, guard it so that we don't leak it. */
  eti = g_type_info_get_param_type (ti, 0);
  lgi_gi_info_new (L, eti);
  eti_guard = lua_gettop (L);

  /* Create table to which we will deserialize the list. */
  lua_newtable (L);

  /* Go through the list and push elements into the table. */
  for (i = list, index = 0; i != NULL; i = g_slist_next (i))
    {
      /* Get access to list item. */
      GIArgument *eval = (GIArgument *) &i->data;

      /* Store it into the table. */
      lgi_marshal_2lua (L, eti, NULL, dir, (xfer == GI_TRANSFER_EVERYTHING) ?
			GI_TRANSFER_EVERYTHING : GI_TRANSFER_NOTHING,
			eval, LGI_PARENT_FORCE_POINTER, NULL, NULL);
      lua_rawseti(L, -2, ++index);
    }

  /* Free the list, if we got its ownership. */
  if (xfer != GI_TRANSFER_NOTHING)
    {
      if (list_tag == GI_TYPE_TAG_GSLIST)
	g_slist_free (list);
      else
	g_list_free (list);
    }

  lua_remove (L, eti_guard);
  return 1;
}
Example #5
0
File: marshal.c Project: ntd/lgi
static void
marshal_2lua_array (lua_State *L, GITypeInfo *ti, GIDirection dir,
		    GIArrayType atype, GITransfer transfer,
		    gpointer array, gssize size, int parent)
{
  GITypeInfo *eti;
  gssize len = 0, esize;
  gint index, eti_guard;
  char *data = NULL;

  /* Avoid propagating return value marshaling flag to array elements. */
  if (parent == LGI_PARENT_IS_RETVAL)
    parent = 0;

  /* First of all, find out the length of the array. */
  if (atype == GI_ARRAY_TYPE_ARRAY)
    {
      if (array)
	{
	  len = ((GArray *) array)->len;
	  data = ((GArray *) array)->data;
	}
    }
  else
    {
      data = array;
      if (g_type_info_is_zero_terminated (ti))
	len = -1;
      else
	{
	  len = g_type_info_get_array_fixed_size (ti);
	  if (len == -1)
	    /* Length of the array is dynamic, get it from other
	       argument. */
	    len = size;
	}
    }

  /* Get array element type info, wrap it in the guard so that we
     don't leak it. */
  eti = g_type_info_get_param_type (ti, 0);
  lgi_gi_info_new (L, eti);
  eti_guard = lua_gettop (L);
  esize = array_get_elt_size (eti);

  /* Note that we ignore is_pointer check for uint8 type.  Although it
     is not exactly correct, we probably would not handle uint8*
     correctly anyway, this is strange type to use, and moreover this
     is workaround for g-ir-scanner bug which might mark elements of
     uint8 arrays as gconstpointer, thus setting is_pointer=true on
     it.  See https://github.com/pavouk/lgi/issues/57 */
  if (g_type_info_get_tag (eti) == GI_TYPE_TAG_UINT8)
    {
      /* UINT8 arrays are marshalled as Lua strings. */
      if (len < 0)
	len = data ? strlen(data) : 0;
      lua_pushlstring (L, data, len);
    }
  else
    {
      if (array == NULL)
	{
	  /* NULL array is represented by empty table for C arrays, nil
	     for other types. */
	  if (atype == GI_ARRAY_TYPE_C)
	    lua_newtable (L);
	  else
	    lua_pushnil (L);

	  lua_remove (L, eti_guard);
	  return;
	}

      /* Create Lua table which will hold the array. */
      lua_createtable (L, len > 0 ? len : 0, 0);

      /* Iterate through array elements. */
      for (index = 0; len < 0 || index < len; index++)
	{
	  /* Get value from specified index. */
	  GIArgument *eval = (GIArgument *) (data + index * esize);

	  /* If the array is zero-terminated, terminate now and don't
	     include NULL entry. */
	  if (len < 0 && eval->v_pointer == NULL)
	    break;

	  /* Store value into the table. */
	  lgi_marshal_2lua (L, eti, NULL, dir,
			    (transfer == GI_TRANSFER_EVERYTHING) ?
			    GI_TRANSFER_EVERYTHING : GI_TRANSFER_NOTHING,
			    eval, parent, NULL, NULL);
	  lua_rawseti (L, -2, index + 1);
	}
    }

  /* If needed, free the original array. */
  if (transfer != GI_TRANSFER_NOTHING)
    {
      if (atype == GI_ARRAY_TYPE_ARRAY)
	g_array_free (array, TRUE);
      else
	g_free (array);
    }

  lua_remove (L, eti_guard);
}
Example #6
0
File: marshal.c Project: ntd/lgi
int
lgi_marshal_field (lua_State *L, gpointer object, gboolean getmode,
		   int parent_arg, int field_arg, int val_arg)
{
  GITypeInfo *ti;
  int to_remove, nret;

  /* Check the type of the field information. */
  if (lgi_udata_test (L, field_arg, LGI_GI_INFO))
    {
      GIFieldInfo **fi = lua_touserdata (L, field_arg);
      GIFieldInfoFlags flags;

      /* Check, whether field is readable/writable. */
      flags = g_field_info_get_flags (*fi);
      if ((flags & (getmode ? GI_FIELD_IS_READABLE
			: GI_FIELD_IS_WRITABLE)) == 0)
	{
	  /* Check,  whether  parent  did not  disable  access  checks
	     completely. */
	  lua_getfield (L, -1, "_allow");
	  if (!lua_toboolean (L, -1))
	    {
	      /* Prepare proper error message. */
	      lua_concat (L,
			  lgi_type_get_name (L,
					     g_base_info_get_container (*fi)));
	      return luaL_error (L, "%s: field `%s' is not %s",
				 lua_tostring (L, -1),
				 g_base_info_get_name (*fi),
				 getmode ? "readable" : "writable");
	    }
	  lua_pop (L, 1);
	}

      /* Map GIArgument to proper memory location, get typeinfo of the
	 field and perform actual marshalling. */
      object = (char *) object + g_field_info_get_offset (*fi);
      ti = g_field_info_get_type (*fi);
      lgi_gi_info_new (L, ti);
      to_remove = lua_gettop (L);
    }
  else
    {
      /* Consult field table, get kind of field and offset. */
      int kind;
      lgi_makeabs (L, field_arg);
      luaL_checktype (L, field_arg, LUA_TTABLE);
      lua_rawgeti (L, field_arg, 1);
      object = (char *) object + lua_tointeger (L, -1);
      lua_rawgeti (L, field_arg, 2);
      kind = lua_tonumber (L, -1);
      lua_pop (L, 2);

      /* Load type information from the table and decide how to handle
	 it according to 'kind' */
      lua_rawgeti (L, field_arg, 3);
      switch (kind)
	{
	case 0:
	  /* field[3] contains typeinfo, load it and fall through. */
	  ti = *(GITypeInfo **) luaL_checkudata (L, -1, LGI_GI_INFO);
	  to_remove = lua_gettop (L);
	  break;

	case 1:
	case 2:
	  {
	    GIArgument *arg = (GIArgument *) object;
	    if (getmode)
	      {
		if (kind == 1)
		  {
		    object = arg->v_pointer;
		    parent_arg = 0;
		  }
		lgi_record_2lua (L, object, FALSE, parent_arg);
		return 1;
	      }
	    else
	      {
		g_assert (kind == 1);
		lgi_record_2c (L, val_arg, arg->v_pointer,
			       FALSE, TRUE, FALSE, FALSE);
		return 0;
	      }
	    break;
	  }

	case 3:
	  {
	    /* Get the typeinfo for marshalling the numeric enum value. */
	    lua_rawgeti (L, field_arg, 4);
	    ti = *(GITypeInfo **) luaL_checkudata (L, -1, LGI_GI_INFO);
	    if (getmode)
	      {
		/* Use typeinfo to unmarshal numeric value. */
		lgi_marshal_2lua (L, ti, NULL, GI_DIRECTION_OUT,
				  GI_TRANSFER_NOTHING, object, 0,
				  NULL, NULL);

		/* Replace numeric field with symbolic value. */
		lua_gettable (L, -3);
		lua_replace (L, -3);
		lua_pop (L, 1);
		return 1;
	      }
	    else
	      {
		/* Convert enum symbol to numeric value. */
		if (lua_type (L, val_arg != LUA_TNUMBER))
		  {
		    lua_pushvalue (L, -1);
		    lua_pushvalue (L, val_arg);
		    lua_call (L, 1, 1);
		    lua_replace (L, val_arg);
		  }

		/* Use typeinfo to marshal the numeric value. */
		lgi_marshal_2c (L, ti, NULL, GI_TRANSFER_NOTHING, object,
				val_arg, 0, NULL, NULL);
		lua_pop (L, 2);
		return 0;
	      }
	  }

	default:
	  return luaL_error (L, "field has bad kind %d", kind);
	}
    }

  if (getmode)
    {
      lgi_marshal_2lua (L, ti, NULL, GI_DIRECTION_OUT, GI_TRANSFER_NOTHING,
			object, parent_arg, NULL, NULL);
      nret = 1;
    }
  else
    {
      lgi_marshal_2c (L, ti, NULL, GI_TRANSFER_EVERYTHING, object, val_arg,
		      0, NULL, NULL);
      nret = 0;
    }

  lua_remove (L, to_remove);
  return nret;
}