lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hi there,

I made a library in C, which parses a special kind of logfile.

The logfile can contain errors (eg. truncated fields). The parser recognizes these errors and can show them. The errors are stored in a structure:

typedef struct mylogerr {
    char    *errmsg;
    size_t  *startpos;
    size_t  *endpos;
} mylogerr;


Each error uses a structure like this, the errors are in a list. The errmsg is a decription of the error, the startpos and endpos show where the error starts and ends.

The library provides a function which iterates over this list:

void read_mylog_err(mylogpool *pool, mylogerr *err);

The library has several bindings, eg. for Python, PHP, Ruby, ... and of cours for Lua.

The errors in the bindings are represented in two lists: first list contains the descriptions, the other contains the indexes, eg:

lineerrors: ['Truncated field', 'Missing field']
lineerrorpos: [[132,135], [212,512]]


Now in Lua binding I was able to make this only by this way:

    lua_pushstring(L, "lineerrors");
    lua_newtable(L);
    int errorstable = lua_gettop(L);

    if (l.lineerrcnt > 0) {
        // reset errpool ptr
        l.lineerrpool.currptr = l.lineerrpool.pool;
        mylogerr logerr;
        for (int c=0; c < l.lineerrcnt; c++) {
            read_mylog_err(&l.lineerrpool, &logerr);
            lua_pushinteger(L, c+1);
            lua_pushstring(L, logerr.errmsg);
            lua_settable(L, errorstable);            
        }
    }

    lua_settable(L, maintable);

    lua_pushstring(L, "lineerrorspos");
    lua_newtable(L);
    int errorspostable = lua_gettop(L);

    if (l.lineerrcnt > 0) {
        // reset errpool ptr
        l.lineerrpool.currptr = l.lineerrpool.pool;
        mylogerr logerr;
        for (int c=0; c < l.lineerrcnt; c++) {
            read_mylog_err(&l.lineerrpool, &logerr);

            lua_pushinteger(L, c+1);

            lua_newtable(L);
            subtable = lua_gettop(L);

            lua_pushinteger(L, 1);
            lua_pushinteger(L, *logerr.startpos);
            lua_settable(L, subtable);

            lua_pushinteger(L, 2);
            lua_pushinteger(L, *logerr.endpos);
            lua_settable(L, subtable);

            lua_settable(L, errorspostable);
        }
    }


As you can see I iterate through the list twice, because I don't know how can I handle in two tables parallel.

(This is how this works in Python:

    PyObject *errors = PyList_New(0);
    PyObject *errorspos = PyList_New(0);

    if (l.lineerrcnt > 0) {
        // reset errpool ptr
        l.lineerrpool.currptr = l.lineerrpool.pool;
        mylogerr logerr;
        for (int c=0; c < l.lineerrcnt; c++) {
            read_mylog_err(&l.lineerrpool, &logerr);
            PyList_Append(errors, Py_BuildValue("s", logerr.errmsg));
            PyList_Append(errorspos, Py_BuildValue("[k,k]", *logerr.startpos, *logerr.endpos));
        }
    }
    ...
    PyObject * rv = Py_BuildValue("{s:k,...,s:O,s:O}",
        "linelen",           l.linelen,
        ...
        "lineerrors",        errors,
        "lineerrorspos",     errorspos
    );

)

Is there any more elegant way to handle this?

Thank you,


a.