2009-05-21

libpqtypes

In recent post I've posted part of my library, that deals with PostgreSQL data in binary format. Today, googling for some hints for implementing binary timestamps in double format I've found a reliable library, libpqtypes, which is doing exactly the same as mine (actually more), except it's purpose is PostgreSQL only.
Don't know if it's terrible news or not, as I could adapt my code while using this library and win a lot of time. This is one of the reasons why extensive googling is required before each project.

PostgreSQL binary timestamp functions

While writing libpq wrapper I've run into problems with binary timestamps, which required a lot of debugging and headaches. To avoid your own migraine, feel free to use my code below. Note, however, this code is not perfect, as it's uses long long for timestamps. This will work if your machine is 32bit and your server was compiled with `--enable-integer-datetimes` (highly recommended). If not, You're welcome to patch this code and post it here, so other people will thank you.

2009-05-05

Lua constants

By Lua's nature, it is not possible to create constants. There is a workaround, though, using metatables:

function protect(tbl)
    return setmetatable({}, {
        __index = tbl,
        __newindex = function(t, key, value)
            error("attempting to change constant " ..
                   tostring(key) .. " to " .. tostring(value), 2)
        end
    })
end

constants = {
    x = 1,
    y = 2,
}
constants = protect(constants)

print(constants.x) --> 3
constants.x = 3 --> error: attempting to change constant x to 3

2009-05-01

Lua error message format

I work on the library, which will use Lua. Thinking about the possibility to give a good error structure instead of plain message, I've found that lua_pcall has a nice feature to specify custom error handler function:

lua_pushcfunction(L, error_handler);
luaL_loadfile(L, "file.lua");
lua_pcall(L, 0, 0, -2);

Using this there is a way to get a chunk name and it's error line number:

int error_handler(lua_State* L) {
    lua_Debug d;

    lua_getstack(L, 1, &d);
    lua_getinfo(L, "Sln", &d);

    string err = lua_tostring(L, -1);
    lua_pop(L, 1);

    stringstream msg;
    msg << d.short_src << ":" << d.currentline;
    if(d.name != 0) {
        msg << "(" << d.namewhat << " " << d.name << ")";
    }
    msg << " > " << err;
    lua_pushstring(L, msg.str().c_str());

    return 1;
}
Work's like a charm, except one thing. This is the output from this error handler:
[string "test"]:1 > [string "test"]:1: attempt to index global 'a' (a nil value)

Why? Oh, why the Lua guys are putting assembled error message with chunk name and line number if I use my own error handler? IMHO, this is wrong. There is no other way to give a user nice message except parsing. Actually parsing of such message is easy, but.. the Lua guys have changed error message format a few times already. I'm pissed!

2009-04-30

Mingw on Linux

I'm using MinGW for years, but never tried to use it on Linux machine as a crosscompiler. Today I've had first experience. First thing I've noticed is how actually easy to install such environment - there is a totally automated build script available from MinGW site.
Pros:
  • One environment
  • Speed. Native environment vs MSys is much, much faster.
Cons:
  • Building non-Linux things on Linux means transferring them from one machine to another.

2009-04-29

Fastest way to create database in PostgreSQL

This will create database and it's associated role from Linux shell:
su postgres
createuser -SDRPE user
createdb -E UTF8 -O user database

Fixing OpenSUSE Home/End keys

Comment lines 135-136 in /etc/inputrc :
#"e[1~":       history-search-backward
#"e[4~":       set-mark

2009-04-27

Icon and version information resource file

This should be an update for one of the recent posts.

resource.rc:
ID ICON "path/to/my.ico"
...the ID can be anything. It doesn't matter unless it is referred in the code.

Run windres as follows:
windres resource.rc -O coff -o resource.o
Include resource.o along with other object files while linking, e.g.,
g++ -o app obj1.o obj2.o resource.o

And, at no extra charge, it is possible to include version information to the application, adding the following boilerplate to resource.rc file:
1 VERSIONINFO
FILEVERSION     1,0,0,0
PRODUCTVERSION  1,0,0,0
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904E4"
        BEGIN
            VALUE "CompanyName", "Company name"
            VALUE "FileDescription", "Application name"
            VALUE "FileVersion", "1.0"
            VALUE "InternalName", "my_app"
            VALUE "LegalCopyright", "Copyright info"
            VALUE "OriginalFilename", "my_app.exe"
            VALUE "ProductName", "My App"
            VALUE "ProductVersion", "1.0"
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1252
    END
END

Links:
- Original post
- Additional info

Credit goes to Evan McLean.

2009-04-16

C Lua snippets

Get currently executed chunk name:
lua_Debug lua_info;
lua_getstack(L, 0, &lua_info);
lua_getinfo(L, "n", &lua_info);
string name = lua_info.name;
Opposite to lua_register:
lua_pushnil(L);
lua_setglobal(L, name.c_str());
stack_dump in C++ flavour ;)
static void stack_dump (lua_State *L) {
    int top = lua_gettop(L);
    for(int i = 1; i <= top; i++) {
        int t = lua_type(L, i);
        switch(t) {
            case LUA_TSTRING:
                cout << "'" << lua_tostring(L, i) << "'";
                break;
            case LUA_TBOOLEAN:
                cout << (lua_toboolean(L, i) ? "true" : "false");
                break;
            case LUA_TNUMBER:
                cout << lua_tonumber(L, i);
                break;
            default:
                cout << lua_typename(L, t);
                break;
        }
        cout << "  ";
    }
    cout << endl;
}

2009-04-12

Gettext compilation on MSys

Trying to build gettext library on MSys I've got some errors related to pthread. Included readme states you need to have Cygwin for that. For those, who prefer MSys over Cygwin here goes a quick fix:
./configure
Add -lpthread to LIBS section in gettext-runtime/src/Makefile and gettext-tools/src/Makefile.
Remove tests target from gettext-runtime/Makefile and gettext-tools/Makefile.
make; make install
Be happy.