Thursday, August 30, 2007

C++ String-Utils

Ever had the problem of wanting to use (s)printf to format a string into an STL/StdC++ std::string instance? The only thing STL says is, "use strstream", which I don't agree with ... (s)printf is easier to use once you get used to the %s stuff, and often cleaner to read. Thus, I wrote my own method ... maybe I just used to much String.format() in Java ;-)

StringUtils.hh

#ifndef STRINGUTILS_HH_
#define STRINGUTILS_HH_

#include <string>


std::string formatString(const char* format, ...); 

#endif /*STRINGUTILS_HH_*/

StringUtils.cc

#include "StringUtils.hh"
#include "BufferUtils.hh"

#include <stdarg.h>
using std::string;

/**
 No need to be afraid about memory leaks, segfaults 
   or buffer overflows (hopefully)
 - the 2kB buffer is freed on return (destructor)
 - the std::string is instantiated before the 
   buffer is freed, and returned on the stack
 - vsnprintf checks the buffer length, and the last char 
   is ensured to be a '\0'
*/
std::string formatString(const char* format, ...) {
 Buffer buffer(2048);
 va_list vl;
 va_start(vl, format);
 vsnprintf(buffer, buffer.bufferSize(), format, vl);
 buffer[buffer.bufferSize()-1] =0;
 return string(buffer);
}

C++ Buffer-Utils

A common C++ problem: allocate some memory block, use it inside a function, and make sure the memory block is freed when exiting the function, even if an early return statement, an exception (or a segfault) or s.th. happens. Best way: Create a class, allocate the memory block in the constructor and free it automatically in the destructor. Instantiate the class locally (i.e., on the stack), problem solved. Some conversion operators to get the mem block as char*, void* etc needed ... Additionally, a small method to nullify a pointer after free'ing the allocated memory with free(). Of course, when using C++, the clean way would be to use new char[] and delete[] ... yet I don't like these ones when I work with an unspecified memory block.

BufferUtils.hh

#ifndef BUFFERUTILS_HH_
#define BUFFERUTILS_HH_

#include <cstdlib>

void freeAndNull(void* &pBuffer);

class Buffer {
private:
 int miBufferSize;
 void* mpBuffer;
 
public:
 Buffer(int bufferSize) 
  : miBufferSize(bufferSize), mpBuffer(malloc(bufferSize)) { 
  // empty
 };
 
 ~Buffer() {
  freeAndNull(mpBuffer);
 }
 
 int bufferSize() { 
  return miBufferSize;
 }
 
 operator char*() {
  return (char*)mpBuffer;
 }

 operator void*() {
  return mpBuffer;
 }
};

#endif /*BUFFERUTILS_HH_*/

BufferUtils.cc

#include "BufferUtils.hh"

void freeAndNull(void* &pBuffer) {
 if (pBuffer)
  free(pBuffer);
 pBuffer = NULL;
}

GPG and IDEA

There are several posts and publications out there on the net about why not to use IDEA with gpg, and how to install the idea.dll plugin if you do it anyway. Yet we did not finde any information about what to do if a certain private/public key pair wants to use IDEA only, possibly, because it was created with pgp2 compatibility. Yet there are some easy steps to change the preferred ciphers of a key, and thus to avoid IDEA when using the key for encryption (especially encrypting to self and thus for all gpg mails that the person sends).

gpg --edit-key 0x12345678
pub  1024D/######## created: 2007-02-03  expires: never     usage: SC
                     trust: unknown      validity: unknown
sub  2048g/########  created: 2007-02-03 expires: never     usage: E
[ unknown] (1). user <mail>

Command> showpref
[ unknown] (1). user <mail>
     Cipher: [1], CAST5, AES256, AES192, AES, 3DES, TWOFISH
     Digest: SHA1
     Compression: ZIP, Uncompressed
     Features: MDC, Keyserver no-modify
the [1] stands for IDEA as the (first) preferred cipher, though it is not a known one in the current gpg installation ... otherwise, IDEA should stand there. So, just set the prefs ... unfortunately, all of them have to be set in one command as a string ...
Command> setpref AES256 AES192 AES CAST5 3DES SHA1 SHA256 RIPEMD160 ZLIB
BZIP2 ZIP Uncompressed MDC
You can do this only with your own key, of course, and need to enter your passphrase (1). Test it, and publish the key anew to the usual key servers. As the preferences are set per user id, and one key may contain a bunch of them, you might have to set the prefs for all user ids seperately ... I didn't try yet. if anything breaks, use setpref w/o any parameters to reset to default values.
Command> setpref
Maybe this helps you as well, if no one else can decrypt the mails you wrote with thunderbird, enigmail and gpgp ... (1) If you are running on windows and use German Umlauts or other diacritical characters, don't be surprised if your passphrase is not accepted in a shell, while enigmail or some other GUI accepts it ... windows cmd.exe has a different character set/code page than the windows system usually uses!

Graphical user interfaces for GPG

BTW, some nice gpg software for windows (linux/unix has gpa, anyway).

A stone age NVidia card and a modern TFT

After some years, I decided to replace my 17'' CRT with a modern 19/20'' TFT. First, had some looks on the internet for good choices, and some in a computer store. Left me with about 4 different Samsung models to choose from. Luckily, I went to the computer store of my confidence ... The guy asked me about my graphics card, s.th. I had not thought about. GeForce 2 MX 200/ELSA Gladiac 311 (32MB, AGP, several years old). "Oh, I'd recommend one of the 16:10 widescreen ones for what you do, yet, your graphics card won't do it ... 1280x1024, the default modes from that time, up to 2048x1536, but no 1400x1050 nor 1680x1050 ... Maybe you should just get a new computer ;-)" Well, I had a check at home ... officially, neither mode is supported (1400x1050 aka SXGA+, 1680x1050 aka WSXGA+), some sites say at least SXGA+ is supported (mainly ebay sellers ...), manuals are not really available as ELSA busted twice since. So I just decided to try it out.

Setting resolution in Xorg

Linux, opensuse 10.2, yast2, sax2: Just set 1400x1050 and it worked. My eyes started running, was hard to read anything, yet it worked. Had to adjust the size and position, of course. Set 1680x1050 and it seemed to work ... yet the Xorg log told me it was using 1600x1024 or s.th. instead. One can't have everything.

Rotating the screen

Next question ... if I get a pivotable TFT, can I do this in Linux? No problem ... Alexander Koenig "told" me
Section "ServerFlags"
...
  Option "RandR" "on"
EndSection

Section "Device"
....
  Option "RandRRotation" "on"
  Option "RenderAccel" "On"
EndSection
and
xrandr -o [left|normal|right]
It just worked.

Setting resolution in windows

Every few weeks or months, I need to boot into my windows system ... there are just a few things which don't really work on wine or vmware player. Found a nice tool EnTech Taiwan PowerStrip that should be able to set manual timings ... didn't need it, though, as the NVidia detonator control centre(1) already has an item "manual timings". Set it to 1400x1050, and got a virtual screen of 1400x1050, and a physical of ... no idea, a bit less. Tried again with 84Hz instead of 85Hz ... and it just works. Seems nvidia tries to use one of the existing modes if the image(?) frequency is already known ... Did the same with 60Hz, and with 1600x1050 ... same results, 84, 80, 60 Hz no problem, 85Hz - virtual screen as wanted, physical smaller. Seems I can buy the Samsung 203B (2) after all ;-) (1) center ;-) (2) Sorry, German page

Thursday, August 16, 2007

C++ typesafe casting

Often, C++ classes are just casted to what is needed by

Subclass* sc = (Subclass)p;
This can lead to unexpected program behaviour, as no error is thrown in the case the p is not an instance of Subclass*; only a bit later, the programm will surely crash. Thus, the clean way is
Subclass* sc = dynamic_cast<SubClass*>(p);
of course, this requires run time type information; they should be available, if libstdc++ is available, too. This can also be used to determine the runtime type of a (class) pointer:
if (dynamic_cast<SubClass*>(p)) { ... }
Unfortunately, the C++ standard does not(?) provide any method to find out about class hierarchies ...

Call-by-reference in Java; StringBuilder

Objects are always passed by reference to Java functions. Thus, any change to the objects are reflected after function return. Of course, changes to the object referencs (the variables themselves) are lost on return. This does not apply to primitives (int, boolean, float). Also, several classes, String, Integer, Double, Boolean, are immutables; thus, it is impossible to change them after construction. Thus, they cannot be used for call-by-reference (demonstration). StringBuffer, on the other hand, can nicely demonstrate this:

static void changeStringBuffer(StringBuffer sb) {
  sb.append(" and some more");
}
public static void main(String[] args) {
  StringBuffer sb("A text");
  changeStringBuffer(sb);
  // this one gives "A text and some more"
  System.out.println(sb.toString());
}
In place of StringBuffer, often the simpler an not-thread-safe class StringBuilder can be used. Swapping, though, does not work:
public static void swap(StringBuffer a, StringBuffer b) {
  StringBuffer c = a;
  a = b;
  b = c;
}
does not really do anything. BTW ... when concatenating Strings, it is better to use StringBuilder and .append, as
String s;
for (.;.;.) s += something; 
is pretty inefficient; for each +=, the String's content needs to be copied into a new instance that has a bit more space at the end for "something". Results in O(n^2) "efficiency", while StringBuilder only needs to get more memory when an internal limit is reached.

C++Threading

OpenThreads as part of OpenSceneGraph contains a number of nice classes for working with threads in C++, using a Posix implemention (*n*x), or the Win32 or Solaris specific one. It is also possible to compile just the three classes that the threading stuff is comprised of, combine it with the appropriate headers, and use it. One thing is missing, though ... an implementation of the "resource acqusition by constructing" pattern. As C++ does not have a "finally" construct, the best solution to ensure a used mutex is freed in all circumstances (earlier return, exceptions, SEGV, ...) is to create a class that locks the mutex on construction and frees it on destruction, and to instantiate this class when needing the mutex (on the stack, of course, not with new).

class  LockIt {
public:
  LockIt(Mutex& mutex) : mMutex(mutex) { mMutex.lock(); }
  virtual ~LockIt() { mMutex.unlock(); }
private:
  Mutex& mMutex;
};
A Mutex called mMutex is defined somewhere; then, you can use it
{
LockIt(mMutex);
// work locked
}
// lock on mMutex automatically released
The thread helpers that are part of the boost class library are far more powerful in this direction, they also contain various lock acquisition classes. Boost will also be part of the next release of the C++ standard ... on the other hand, it is really large (a thousand header files, if I counted right), and not that easy to use ...

C++-Documentation: Links

Interesting documentation links about C++

Tutorials

LibStdC++

Threading

Resource allocation

Humor

java.util.ArrayList != std::list

When using "lists" in Java, ArrayList is usally the choice. When using list contructs in C++, using std::list is usually not a good idea, as it is implemented as linked list, and therefore all indexed acesses (list[i]) take linear time, and an iteration such as

for (int i=0; i<list.size(); i++) {...}
takes O(n^2)! (Of course, one should not do this in StdC++/STL anyway, but use the iterators.) Thus, std::vector should be used in most cases. Only exception: regularly adding elements somewhere inside the list, which is far more efficient in a (doubly) linked list.