Archive for the ‘C/C++’ Category
First libdiesel release
I’ve just made first version of libdiesel library publicly available. I will not release the sources due to personal constraints, but you’re welcome to use compiled version. So far, there is only MinGW32 static version, but I may compile this library for other platform as well. Just leave me a comment.
Simple TLS library
Last few days I’ve been working on a simple TLS wrapper. So far, client side is finished and working lovely. Next task is to include server part, and when it will be finished I think I’ll make the library public.
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.
{
long long timestamp;
// get long long with correct byte ordering
if(!get(row_number, column_number, ×tamp))
return false;
memset(value, 0, sizeof(struct tm));
long long dDate, date0, time;
date0 = date2j(2000, 1, 1);
time = timestamp;
TMODULO(time, dDate, USECS_PER_DAY);
if(time < (long long)0) {
time += USECS_PER_DAY;
dDate -= 1;
}
// add offset to go from J2000 back to standard Julian date
dDate += date0;
// Julian day routine does not work for negative Julian days
if(dDate < 0 || dDate > (long long)INT_MAX)
return false;
j2date ((int)dDate, &value->tm_year, &value->tm_mon, &value->tm_mday);
dt2time( time, &value->tm_hour, &value->tm_min, &value->tm_sec);
// years in tm starts from 1900
value->tm_year -= 1900;
// months in tm are zero based
value->tm_mon--;
// mark this as *no* time zone available
value->tm_isdst = -1;
return true;
}
bool Database::put(struct tm* value)
{
// Julian day routines are not correct for negative Julian days
if(!IS_VALID_JULIAN(value->tm_year + 1900, value->tm_mon + 1, value->tm_mday))
return false;
long long dDate, time, timestamp;
dDate = date2j(value->tm_year + 1900, value->tm_mon + 1, value->tm_mday) -
date2j(2000, 1, 1);
time = time2t(value->tm_hour, value->tm_min, value->tm_sec);
timestamp = dDate * USECS_PER_DAY + time;
// check for major overflow
if((timestamp - time) / USECS_PER_DAY != dDate)
return false;
// check for just-barely overflow (okay except time-of-day wraps)
if((timestamp < 0 && dDate >= 0) ||
(timestamp >= 0 && dDate < 0))
return false;
long long *ts = ×tamp;
unsigned long l1 = htonl(*((unsigned long *) ts + 0));
unsigned long l2 = htonl(*((unsigned long *) ts + 1));
unsigned long long ll = l1;
ll = (ll << 32) + l2;
return put(OID_DATETIME, (char*) &ll, sizeof(long long));
}
All the functions from this code are available in postgres sources, except put and get which I will not publish due to specifics of my code. If you’re using this, you should already have your own functions for argument saving into some buffer.
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:
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:
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:
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!
Icon and version information resource file
This should be an update for one of the recent posts.
resource.rc:
…the ID can be anything. It doesn’t matter unless it is referred in the code.
Run windres as follows:
Include resource.o along with other object files while linking, e.g.,
And, at no extra charge, it is possible to include version information to the application, adding the following boilerplate to resource.rc file:
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.
C Lua snippets
Get currently executed chunk name:
lua_getstack(L, 0, &lua_info);
lua_getinfo(L, "n", &lua_info);
string name = lua_info.name;
Opposite to lua_register:
lua_setglobal(L, name.c_str());
stack_dump in C++ flavour
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;
}
Set up AVR timer interrupt
void init_isr_timers() {
/* OC1A/OC1B disconnected */
TCCR1A = 0;
/* CTC mode, top in OCR1A / Timer clock = CLK/1024 */
TCCR1B = (1<<WGM12)|(1<<CS12)|(1<<CS10);
/* set OCR1A top value for 20Hz (10 periods in one second) */
/* 0x0168 for CPU @ 7.3728MHz */
OCR1A = 0x0168;
/* enable Timer/Counter 1 interrupt */
TIMSK = (1<<OCIE1A);
}
/* timer/counter 1 interrupt handler */
ISR(TIMER1_COMPA_vect) {
/* Ohhh, lovely! :) */
}
int main() {
/* initialize timer interrupt */
init_isr_timers();
/* enable interrupts */
sei();
/* main loop */
for(;;) {}
}