Visar inlägg med etikett SOURCE CODE. Visa alla inlägg
Visar inlägg med etikett SOURCE CODE. Visa alla inlägg

Get free memory in Erlang

Here is how you get the amount of free memory available in Erlang:

17> application:start(os_mon).
...
18> memsup:get_system_memory_data().
[{total_memory,2125283328},
 {free_memory,188440576},
 {system_total_memory,2125283328}]

Joining stringlists

Here is how you join a list of strings in elisp:

(mapconcat (lambda (x) x) load-path "\n")

It is equivalent to this Python code:

'\n'.join(stringlist)

Example of the LZW algorithm

This is probably old stuff for most of you, but here is my Python implementation of the LZW algorithm.

# The initial LZW tables that maps codes to strings and vice-versa. code_to_str = [chr(i) for i in range(256)] str_to_code = dict((chr(i), i) for i in range(256)) def compress(seq): ''' Returns an LZW compressed list of the input character sequence. ''' output = [] table = dict(str_to_code) s = '' for ch in seq: it = s + ch if it in table: s = it else: output.append(table[s]) table[it] = len(table) s = ch output.append(table[s]) return output def decompress(seq): ''' Returns a decompressed list of the LZW compressed input. ''' table = code_to_str[:] prevcode = seq[0] output = [] output.append(table[prevcode]) for code in seq[1:]: try: entry = table[code] except IndexError: # The lzw special case when code is not yet defined. entry = table[prevcode] entry += entry[0] output.append(entry) table.append(table[prevcode] + entry[0]) prevcode = code return output

Used like this:

data = open('somefile.txt').read() data = compress(data) print decompress(data)

Explanation for how the algorithm works can be found in other places on the net.

Lose weight with MIN, MAX and CLAMP

This article is related to two patches to cairo, #12717 and #12722. Many times in C, you want values in a certain range, or some that are not above or below a certain value. The process which ensures that values are within a certain range is called clamping.

Let us say that you have function that sets the position of something.

void set_pos (Obj *obj, int x, int y) { obj->x = x; obj->y = y; }

Further assume that the position must be contained within obj:s clip rectangle. That could be accomplished using this code:

void set_pos (Obj *obj, int x, int y) { // First clip the values if (x < obj->rect.x) x = obj->rect.x; if (x > obj->rect.x + obj->rect.width) x = obj->rect.x + obj->rect.width; if (y < obj->rect.y) y = obj->rect.y; if (y > obj->rect.y + obj->rect.height) y = obj->rect.y + obj->rect.height; // Then set them obj->x = x; obj->y = y; }

A mathematical way to write the clipping would be something like:

obj->x = x, obj->rect.x <= x <= obj->rect.x + obj->rect.width
obj->y = y, obj->rect.y <= y <= obj->rect.y + obj->rect.height

Time to introduce the MIN and MAX functions and see how they can help us. In C, they can be implemented as macros.

#define MAX(a, b) (((a) > (b)) ? (a) : (b)) #define MIN(a, b) (((a) < (b)) ? (a) : (b))

It should not be any surprise that

x = MAX (x, obj->rect.x)

and

if (x < obj->rect.x) x = obj->rect.x;

is exactly equivalent. We can therefore rewrite the boundary checking code in set_pos to take advantage of these macros:

void set_pos (Obj *obj, int x, int y) { x = MAX (x, obj->rect.x); x = MIN (x, obj->rect.x + obj->rect.width); y = MAX (y, obj->rect.y); y = MIN (y, obj->rect.y + obj->rect.height); obj->x = x; obj->y = y; }

But wait, there is more! The code can be further rewritten if we introduce a CLAMP macro.

#define CLAMP(x, l, h) (((x) > (h)) ? (h) : (((x) < (l)) ? (l) : (x)))

Now we can make the set_pos function even more readable:

void set_pos (Obj *obj, int x, int y) { obj->x = CLAMP (x, obj->rect.x, obj->rect.x + obj->rect.width); obj->y = CLAMP (y, obj->rect.y, obj->rect.y + obj->rect.height); }

Note how similar this code is to the imagined mathematical definition. It is also worth noting that the CLAMP macro doesn't work if the value of the upper bound is lower than the lower bound. That is, if obj->rect.width or obj->rect.height is negative, then the macro will give erroneous results.

Simple to_string function in C

Most languages have ways to serialize objects to strings. But ofcourse, C does not have any. The difficulty of creating one in C, is that the string representation of the object must be freed afterwards. Let us say you have a Rectangle type with the fields x, y, width and height. You might write its to_string function like this:
char * rect_to_string (Rectangle *rect) { char buf[256]; snprintf (buf, 256, "(%d, %d)-(%d, %d)", rect->x, rect->y, rect->width, rect->height); return strdup (buf); }
Note that memory is allocated. A client must therefore make sure to deallocate the string when it is done with it:
char *s = rect_to_string (my_rect); printf ("my_rect is %s\n", s); free (s);
If you forget to free the string bad things will of course happen. You must also not use it inline:
printf ("my_rect is %s\n", rect_to_string (my_rect));
Because that will leak memory. The memory allocated inside strdup continues to live on, but the reference to that memory is gone. What you can, and should do, is to use a static buffer.
char * rect_to_string (Rectangle *rect) { static char buf[256]; snprintf (buf, 256, "(%d, %d)-(%d, %d)", rect->x, rect->y, rect->width, rect->height); return buf; }
Since no memory is allocated, the inline approach works ok. However, if you want the string to survive for any longer periods of times you must still allocate it. The following code demonstrates the bug.
char *rect1_str = rect_to_str (rect1); char *rect2_str = rect_to_str (rect2); printf ("The rectangles are: %s %s\n", rect1_str, rect2_str);
Both variables will point to the same static buffer. And because rect_to_string overwrites the contents of that buffer, only the string representation of rect2 will survive. The solution to this problem is to explicitly allocate strings that must survive:
char *rect1_str = strdup (rect_to_str (rect1)); char *rect2_str = strdup (rect_to_str (rect2)); printf ("The rectangles are: %s %s\n", rect1_str, rect2_str); free (rect1_str); free (rect2_str);
Even with this quirk, I believe the last method is superior. It is very nice to be able to just print out the contents of a struct such as a Rectangle and not have worry about memory problems.

Bloggarkiv