Credits and License details
The source code available in this page is copyright of the following author(s):
The software provided in this page is maintained by:
No warranty of any kind is implied for the uses of the source code provided in this page. It is provided 'as is'. Use at your own risk. See license for details.
This software is licensed under BSD License.
Please contact with the maintainer(s) for other license(s).
To begin, I must ask excuses for my low level of English. In reality, unfortunately, I do not speak English, but after a lot of years dedicated to the world of information technology (and, therefore, compelled to try to read documentation in English), listening music in English and, under these circumstances, trying to learn the language, perhaps I have reached a minimum level that, with the help of a translator, can make my comments understandable. All this in favour of greater universality of what I pretende expose here.
My purpose here is to build, step by step, a library of low/medium level routines for process different types of data. It is a project that exists in my mind a long time. I have already started at different times, under different approaches, but that has never been done completely. This may be the occasion, helped by anyone wishing to make their own conclusions and improvements. In any case, I hope that the routines are instructive for all those who decide to take a look. There may be interesting ideas here.
Since it is desirable to name the library, to avoid conflicting with any other names of many packages circulating around, I have decided to call it the "valarLib". The "Valar" are, in the Tolkien's cosmology (at least in the Spanish version), the Ultimate Powers of Nature, those who have created the Earth (even the Universe) and build the events that occur in our world (see "The Simarillion" and related books: "The lord of rings", "The hobbit" and others). I have chosen this name because it is the first thing that has happened to me and because it highlights my admiration for the works of this author. I hope that does not exist around another package of routines with this name!.
This document, and also the source code files, may be changed as the project advances. Any changes will be annotated appropriately at the time it occurs. This first version is September 1, 2008.
Any suggestion, comment or contribution may be directed to my e-mail (anxocarril) on this server. I will try to answer everything ... Thank you all for your patience, your interest and your collaborations!
The code is distributed as source code. To be used, you should download and paste it into the source of the project where it will be used. At the moment, there is not distributed in binary format. In the future, perhaps.
The original source code is written in C (in the future, may appear versions of these routines, and other routines, in other languages, in particular, C++ and Pascal). This implies that the source code is distributed in pairs of files: headers (H files) and code itself (C files). Any piece of the library includes a common header file (valarLibDefs.h) which contains all basic definitions for the rest of the modules. This file depends on valarLibConfigure.h file (where you can put some basic configuration symbols). The rest of the source are organized according to their functionality.
In opposition to the concept of competition that dominates the capitalist world where we live, I am a strong supporter of the concept of collaboration. For the world of computers, any programmer knows the horrendous task of develop a project for a multitude of different platforms, each with its own way to operate, forcing the program to be adapted to each particular setup. I will try that the routines are as standard as possible (in a way that they work on any platform) but I will compile and test them under a Linux system and with a compiler of the gcc family (free software!) and using the gnu library. Case sensitivity on file names, and problems with End of Line characters, must be resolved (if exists) accordly with your operating system.
Code write conventions and details
When someone has spent many years writing programs, acquires its own hands to write code. The discussion about whether it's better or not is somewhat useless because there would be many things to discuss and because it is very difficult to set objective criteria for this. The only thing I can do is expose my way of writing code for those who choose to look at what can visualize comfortably.
Code indentation and format
To indent code, I use tabs size 1 (could be substituted by spaces). All the blocks were indented with 2 tabs and this also affects the brackets for opening and closing the block (where they exist). When I speak of blocks of instructions, I talk about:
- The bodies of the functions (I do not like the convention, generally adopted, of placing the brackets at the end of the header function).
- The bodie of an instruction while, for, do ... while, if or switch. For an instruction if, the word else (when exists) is indented only 1 tab. For an instruction switch, the blocks of instructions of each case section, are indented 2 tabs.
Every line of code begins with so many tabs as necessary to fit within the block of instructions to which it belongs (0 or more). If you do not like my format, you can reformat source code manually ... (sorry!!!).
To write the source code, I use no more than 80 columns wide (because the old printers had this limit for printing). When one line of code took more than 80 columns (even 79), is broken, using the Enter key, into several pieces. These pieces are indented significantly, from the point of origin of the line, with spaces (not with tabs) to be clearly remarked as part of a single line of code (there is no fixed rule for the number of spaces used in each case, nor for the breakpoint positions. It depends on the content of the line).
In choosing identifiers for the names of functions or variables, I try that they are enough long so that its name is significant. The names of functions or global variables are longer than the names of local variables (among these variables, loop always taken the classical names i, j, k ..). Apart from this, I follow these rules:
- Identifiers that represent a data type begin with a prefix "tt". In C, they are only aliases defined with typedef (for example, ttMemCell, in file valarLibDefs.h). In other languages, may represent real data types. Identifies that represent a pointer to a data type have the same name of data type with a "Ptr" suffix (example, ttMemCellPtr).
- Enum bassed data types are used frequently. Generally, these data types enumerates a set of increasing values beginnig with a "invalid value" (generally, the -1 value) and ending with a "count of values" value (which is the number of items in this data type. For example, ttDataAlignment in the valarLibDefs.h file). Another way to define values for a "conceptual data type", is by using preprocessor #define symbols (a similar convention is used in this case).
- Struct (or union) bassed data types are also used frequently. In this case, a preprocessor #define symbol is provided as the "null value" for the data type. The name of this symbol is constructed as this: The "ddNull" prefix and the name of defined data type without the "tt" prefix.
- In all cases, a "pointer to data type" is provided following the explained pointer type name convention (ending with a "Ptr" suffix).
- Global variables for a module (shared by all the functions of a module but not exported to other modules) begin with a prefix "lv".
- Global constants for a module begin with a prefix "gv".
- Global variables for an application (shared by all modules) begin with a prefix "gv".
- Global constants for an application begin with a prefix "gc".
- The symbols defined for the preprocessor (constants) begin with a prefix "dd", except symbols for control the reinclusion of a header file (see below).
- The symbols for control the reinclusion of a header file, are formed by two underscores, the file name without extension, an underscore, the letter h, two underscores (example: __valarLibDefs_h__).
- The symbols defined for the preprocessor (macros) begin with a prefix "mm".
I have tried to put many comments in the source code (never are enough). There is always one at the beginning of each file containing the name of the file and a set of notes indicating the file content. For the remainder of the source code I use different comment formats (no fixed rule for this but, obviously, the comments they occupy more lines correspond to larger sections of code). About comments, I make the following remarks:
- Comments are important in macro definitions: For each macro definition, a "conceptual prototype" is included before as a comment. The conceptual prototype is the pattern for "macro calls", considering the macro as if it were a function. Remember that, however, a macro is not a function and can be called with a different set of arguments (see below for an explanation of preprocessor defined symbols). The macro comment shows, approximately, the correct way to work. In these comments:
- ttValue represents a value of any type supported by the C compiler (that is, int, char, float or double).
- ttInteger represents an integer value.
- ttUnsigned represents a unsigned integer value.
- TODO comments may appear at any point of code. This introduces a section of code in which there are still things to do, which may be supplied by the author or any collaborator who wish to do so. These comments will be headed by the word TODO (in uppercase).
- Important comments will be headed by the word NOTE (in uppercase).
- (Added at September, 29, 2008) CHANGELOG notes can appear at any point to reflect changes made in the source code. These notes are formed by two comments, one that marks the beginning point of the changes made and other to mark the end. CHANGELOG comments have a special format, as follows:
/* = CHANGELOG-START; mm/dd/yyyy; label = Explanation */ source code /* = CHANGELOG_END; mm/dd/yyyy; label = */
- mm/dd/yyyy is the date on which the change was made
- label is a short description of change
- Explanation (optional) is a detailed description of change
Header CHANGELOG comment, as you can see, is delimited by equal characters within the normal C comment delimiters (this header can occupy more than one line). It is possible to write a parser to extract these comments from source files!
Example (extracted from valarLibBits.h file):
/* = CHANGELOG-START; 09-11-2008; Source change = Old definition of this macro pair is strange... Ever more, results may be not strictly valid. Now they work correctly */ /* ttUnsigned mmGetBitMaskForBitIndex(ttBitNumber aBitIndex). Obtains an integer, all 1's from bit 0 to bit aBitIndex (zeroes for the rest) */ #define mmGetBitMaskForBitIndex(b) ((b)<0?0: \ (ddMaxUnsignedValue>>(ddUnsignedBitCount-((b)+1)))) /* ttUnsigned mmGetBitMaskForBitCount(ttBitCount aBitCount). Using the previous macro, obtains an integer for a count of bits (result can be 0 or greater) */ #define mmGetBitMaskForBitCount(b) ((b)<=0?0: \ (ddMaxUnsignedValue>>(ddUnsignedBitCount-(b)))) /* The old version (as reference) #define mmGetBitMaskForBitIndex(b) \ (ddMaxUnsignedValue>>(ddUnsignedBitCount-((b)+1))) #define mmGetBitMaskForBitCount(b) ((b)==0?0: \ mmGetBitMaskForBitIndex((b)-1)) */ /* = CHANGELOG-END; 09-11-2008; Source change = */
Preprocessor defined symbols
The preprocessor defined symbols (constant and macros) are often used in the source code because they provide greater clarity and, in the case of macros, more speed and flexibility. With the constant symbols, no problem. With macros, you must remember that, if they are similar in some respects to the functions, they are not functions. They have the advantage that can be invoked with different arguments types but have the disadvantage that they are "not secure": Some macros may produce strange results or inefficient performance with some arguments, especially when used with parameters containing an ++ or -- operator or a call to a function, because the expressions with a macro is invoked can be evaluated more than once. Be careful with argument values when you use macro definitions. A warning comment appears in some cases when a macro is "not secure" (when I remember that). For these macros that are "not secure", an alternative function is provided (when I remember) with the same name of the macro but without the prefix "mm" (this function, simply makes a "call to the macro" but is secure because the arguments are evaluated before macro invocation).
Project state at september 29, 2008
- Technical notes section has changed at September 29, 2008 to reflect changelog comment formats.
- Routines for copy and compare array of bits in valarLibBits module. Done.
- Current version of valarLibBits module was tested and works ok.
Next in this project
In valarLibBits module:
- Functions to do logical operations with bit arrays
- A ttBitPtr class for C++ (based on ttBitPointer structure)
A new module valarLibSetTypes: Handling of set types (based on bit handling routines)
Two new modules valarLibSort and valarLibSearch: Sort and search routines
A new module valarLibClassicalStr: Handling of classical strings (with Pascal strings compatibility)
Module valarLibIpc: Routines for InterProcess Communication