2004-04-23

dkstd 2.26

Et voici la dernière version de ma bibliothèque de développement C++. Pas mal de polissage. Les grosses améliorations concernent la classe de tableau dynamique (CArray) qui est beaucoup plus rapide, et les classes de gestion de chaine de caractères (CString et CWString) qui sont plus rapides aussi. Le support de l'Unicode et de l'UTF-8 est aussi amélioré.

Pour la prochaine version j'ai encore des idées pour améliorer la gestion des chaines de caractères. Je compte aussi améliorer une classe de document XML que j'ai faite afin qu'elle ne gère plus que l'Unicode.

Je trouve qu'il manque quelque chose de cruciale à cette bibliothèque pour qu'elle soit un peu plus utilisée : une documentation. Ça fait partie de mes projets :) Je pense qu'elle contient pas mal de fonctions qui pourront aider les développeurs (en tout cas elle m'aide depuis 1998). Je vois parfois des projets dans SourceForge dont l'objet est déjà couvert par une partie de la dkstd.

Digression...

Parfois j'arrive un peu aux limites du système en matière d'optimisations ou de fonctionnalités. On en parle assez souvent avec Anubis, le bonheur pour un développeur c'est d'avoir des outils de développement bien homogènes.

Je vais prendre l'exemple de la classe de chaine de caractères que j'ai développée, la version qui permet de gérer de l'Unicode en UCS-2 (je simplifie le code pour davantage de clareté).

Ça, c'est ma structure de chaine de caractères :

// Ma classe de chaine
class CWString
{
	CWStringData* m_pData;
};

// Les données de la chaine. Plusieurs CWString peuvent pointer sur la même instance de CWStringData
class CWStringData
{
	int32 m_nLength;    // Taille en caractères
	int32 m_nRefCount;  // Combien de fois ces données sont pointées
	wchar m_szBuffer[]; // Les caractères
};

Dans un programme en C++, on voudra initialiser une CWString à partir d'une chaine issue de l'exe :

void MyFunction()
{
	CWString str = L"Plop"; // Le L c'est pour avoir une chaine en UCS-2
}

Dans l'exemple précédent, la chaine « Plop » sera stockée dans le fichier exécutable finale sous la forme d'une suite de caractères UCS-2 (16 bits chacun). Voici comment elle apparaitra :

Quatre caractères sur 16 bits respectant le standard Unicode,
avec un caractère à 0 à la fin pour marquer la fin de la chaine :

0050 006C 006F 0070 0000

La variable str sera initialisée à partir de cette chaine, cela veut dire :

  • allouer de la mémoire pour recevoir la chaine « Plop » ;
  • recopier la chaine « Plop » de l'exécutable en mémoire, vers le buffer fraichement allouée par la variable str.

Les soucis sont les suivants :

  • l'allocation mémoire peut rater ;
  • on perd du temps machine à recopier une chaine ;
  • on perd de la mémoire à avoir deux fois la même chaine : « Plop » dans l'exécutable, et « Plop » dans le buffer de str.

Maintenant imaginez un compilateur C++, générant du code légèrement personnalisé, et un format de fichier exécutable personnalisé aussi. Appelons le compilateur ChuCpp, et ChuExe le format d'exécutable. Je pourrais faire générer des chaines de caractères compatibles avec ma classe CWStringData, celle-ci étant ensuite stockées dans mon fichier au format ChuExe. Résultat, on trouvera :

Le premier mot de 32 bis est la taille (4 caractères), puis le compteur de références, puis les caractères :

00000004 7FFFFFFF 0050 006C 006F 0070

Ainsi, quand on affectera une CWString à partir d'une chaine constante : CWString str = L"Plop";, l'opération sera immédiate, ne risquera pas de faillir en raison d'un manque de mémoire et ne prendra pas trop de temps machine.

Pas mal, pas mal, mais il y a encore des choses à améliorer.

À l'heure actuelle, j'utilise essentiellement de l'UCS-2 pour mes chaines Unicode, car les systèmes que je rencontre utilisent ce format là aussi. Je reste donc 100% compatibles avec ceux-là. Un exemple sous Windows :

// SetWindowTextW est une fonction Windows pour fixer le titre de la fenêtre, et qui attend une chaine en UCS-2

CWString strTitle = L"ChuEditor - ";
strTitle += strDocumentFileName;

SetWindowTextW(hWnd, strTitle);

Très bien, mais l'UCS-2 ne permet pas de représenter tous les caractères définis par Unicode. J'aimerais bien dans ce cas utiliser de l'UCS-4 (32 bits par caractères). Sauf que là je suis coincé, je ne vois pas comment donner de l'UCS-4 à Windows.

Maintenant imaginez un système d'exploitation qui ne travaillerait qu'avec des CWString basées sur UCS-4. Appelons-le ChuOS. Combiné au compilateur ChuCpp, et au format d'exécutable ChuExe, on pourrait avoir une bibliothèque de développement C++ à la fois optimisée et facile d'emploi, cohérente avec tout le système. Tant qu'à faire, on nommerait cette bibliothèque « ChuSys », et le système l'utiliserait en interne. On pourrait même y mettre quelques fonctions en assembleur qui vont bien. Au final, le devéloppeur se verrait proposé une plateforme très intéressante pour ses développements.

Certes, on aura dû remanier un peu le tout (comme perdre un pourcentage de compatibilité C++). On constate aussi que l'on perd la notion d'indépendance de plateforme, mais je fais partie de ceux qui pensent que le jeu en vaut la chandelle.

Bon, la dkstd ne prend pas cette direction. Son but est de rendre le développement de logiciels pratique et portable (testé sous Linux et Windows, peut-être d'autres systèmes ?) le tout en respectant le standard C++. Mais mon imagination travaille :)