[ESP32) connaitre la longueur d'une chaine avec deux pointeurs

C'est surtout un visualiseur, si je me lance dans un éditeur sur un terminal je ne verrai jamais le bout, pas sur aussi que les terminaux gère l'utf8 sur un environnement à base de micro controleur. Par contre ca m'intéeresserai de connaitre comment faire le décodage d'un UTF8.

Comme je disais sur un terminal ce n'est pas la même logique que dans un pc normal. sous windows j'ai déjà fait un éditeur qui prend en charge tout les encodage existant, avec scintilla, par exemple, vous n'avez plus rien à faire, c'est facile, mais sur un terminal c'est une autre paire de manche.

En gros je visualise un fcihier texte , avec gestion des touches up, down, pageup, page down, home, end et avec une recherche, c'est tout.

J'ai fait cela car parfois je voulais voir le contenu d'un fichier de la sdcard. idem pour le visualiseur hexa, c'est plus simple de voir un fichier dans un visualiseur que de faire un cat avec un more.

Je suis désolé mais je ne comprends pas du tout ta problématique, ni tes explications :frowning: .

Si tu veux visualiser un fichier texte en Hexa, car du coup c'est pas du binaire :slight_smile:
Justement suivant la provenance du fichier texte, c'est important de savoir si tu as les bons caractères de retour à la ligne et donc de bien afficher toutes les valeurs ascii en hexa.

Idem, je ne vois pas ce que ça change ton OS, de quel limite parle tu ?

Pourquoi ?, puisque tu visualise ce qu'il y a sur ta carte SD

En gros la valeur du premier octet t'indique combien d'octet(entre 1 et 4) est utilisé pour ton caractères.
mais le mieux est de regarder la description de wikipédia ou les différentes rfc en bas de page si tu as du courage :slight_smile:

Oui mais je n'ai rien modifié concernant l'éditeur hexa, je vois ce qu'ont voit dans un vrai éditeur hexa, comme si tu prenais un editeur hexa sous windows.

Concernant l'OS oui ca change beaucoup, sous linux la difficulté aurait été divisé par trois.
car on trouve les sources partout sur le net, j'ai été obligé de réécrire des fonctions linux qui n'existe pas sous windows ou arduino, en tous cas je m'en suis servi, par exemple la commande wc, la parti comptage de lignes j'ai du la refaire, elle n'existe pas sous windows, c'est un exemple mais il y en a plein d'autres.
La gestion des escape code, par exemple la touche F12 qui ne fonctionne pas mais sous linux oui.

Pourquoi ?, puisque tu visualise ce qu'il y a sur ta carte SD
Je n'ai pas compris ta réponse par rapport à ma question.

Merci pour l'info concernant l'UTF8, je regarderais à l'occasion, mais sur un terminal, je ne suis pas sur de l'utiliser, comme je disais, je ne pense pas à ma connaissance qu'un terminal DEC ou VT100, VT220 etc, gère l'UTF8, ca ne gere que du code ascii de 0 à 127, voir peut être et pasur de 127 à 255, sauf les émulateur tel que putty, teraterm etc .., là je parle d'un vrai terminal.

Attention: tout ce que je fais ca concerne un terminal et non windows. avec un windows ont fait facilement tout ce qu'on veut, surtout avec les API, les bibliothèques, sur un terminal on est limité qu'a du caractère, pas de graphisme ni rien.

vous pouvez cependant avoir des caractères UTF8 dans un fichier texte, ça va faire des caractères bizarres à l'écran sans doute.

oui si je copie un fichier venant du pc que je met sur la carte sd et que j'essaye de le lire c'est clair.
ce n'est pas mon cas la carte est prévu pour un terminal, je répète encore c'est important.
sur la carte sd il n'y a que des fichier texte ascii et binaire.
ont peu émuler un pc de type 80186 sur cette carte, si tu regarde le code PCemulateur de la lib de fabgl, tu verra qu'il n'a pas de notion d'UTF8.

On peut flasher un tinybasic dessus, mais il ne gère pas l'utf8, en tous cas le code basic, ce sont des fichiers texte.

Après effectivement ce serait pour ma connaissance personnelle essayer d'afficher un texte dans un terminal contenant des caractères UTF8 pour voir ce que ca donne.

à 99% c'est orienté caractères ascii.
Je ne travail pas sous windows, c'est un terminal. il faut penser ascii de 0 à 127.
D'ailleurs je pense que dans le source de fabgl, il n'y a rien concernant l'UTF8.

Sous un environnement arduino, c'est plus difficile.

ce code peut être interessant pour convertir utf8 vers ascii

// ****** UTF8-Decoder: convert UTF8-string to extended ASCII *******
static byte c1;  // Last character buffer

// Convert a single Character from UTF8 to Extended ASCII
// Return "0" if a byte has to be ignored
byte utf8ascii(byte ascii) {
    if ( ascii<128 )   // Standard ASCII-set 0..0x7F handling  
    {   c1=0;
        return( ascii );
    }

    // get previous input
    byte last = c1;   // get last char
    c1=ascii;         // remember actual character

    switch (last)     // conversion depending on first UTF8-character
    {   case 0xC2: return  (ascii);  break;
        case 0xC3: return  (ascii | 0xC0);  break;
        case 0x82: if(ascii==0xAC) return(0x80);       // special case Euro-symbol
    }

    return  (0);                                     // otherwise: return zero, if character has to be ignored
}

et pour une chaine de caractère:

// In Place conversion UTF8-string to Extended ASCII (ASCII is shorter!)
void utf8ascii(char* s)
{      
        int k=0;
        char c;
        for (int i=0; i<strlen(s); i++)
        {
                c = utf8ascii(s[i]);
                if (c!=0)
                        s[k++]=c;
        }
        s[k]=0;
}

demo:

char* s="abcABC äöüß ÄÖÜ €xm²/kg³<";

  Serial.println("UTF8-decoder Test");
  Serial.print("Original: ");
  Serial.println(s);
  utf8ascii(s);
  Serial.print("Extended ASCII-Version ");
  Serial.println(s);

tu parle de commande du coup avec wc, avec bash sur linux, tu as les commande principales de linux de compiler pour windows.
Si c'est bien de la commande wc que tu parle, tu peux faire find /V /C ""
A moins qu'il y a une une fonction wc, dans la librairie C ?

je pensais plus, si tu utilisais la carte SD, pour stocker des choses récupéré par ton Arduino.

La carte SD contient des fichiers pour les emulateurs, si on veut émuler un VIC20, un CPC64 ou un PC xt, il y a les fichiesr .bin pour le bios par exemple.

par contre à l'aide de telnet ou de wget je peut récupérer un fichier pour un besoin spécifique.

Pour éviter de sortir la sd , la brancher sur mon pc, copier le fichier remettre la sd sur la carte FABGL, rebrancher la carte FABGL, j'utilise wget sur un serveur web hebergé sur NAS ou rpi zero.

Pour mes tests je téléchargeais directement sur la carte SD des fichiers text avec le wget, et ca me permettait de vérifier certaines infos à l'aide des visionneurs text et hexdump.

je parlais de wc, car sur mon terminal j'ai quelques commandes que j'ai fait, j'en ai une 50 aine, le minimum pour travailler, dir, cat, rm, telnet,scan,df,copy, wget, keyb etc ...
Je l'ai appelé wc, pour faire référence à des nom de commande, et j'ai pensé à linux, par exemple la commande cat, c'est juste une ouverture de fichier, de lire le contenu et de l'afficher, en prenant en compte les fichiers binaires et les escape codes.

au départ j'avais besoin de wc pour compter les lignes du fichier, et J-M-L ma aidé la dessus.
J'ai quand même récupérer le source de wc, du moins juste la partie comptage de ligne qui est optimisé pour des gros fichiers et je l'ai retranscris sous arduino en C.

Ce que je disais tout à l'heure, sous linux le source existe, sous arduino j'ai du l'adapter.

ha ok, oui Linux utilise des outils qui sont open source.
Après sur Aduino, comme ce n'est pas un Os, ce genre de chose n'est pas fournis en standard.
tu aurais peut être pu trouver une librairie qui fait à peu près ce que tu veux, mais là au final, tu as un truc qui fait exactement ce que tu veux et uniquement ce que tu veux, c'est mieux :+1:
Normalement, tu es du coup obligé de cité tes sources et de toi même respecter les différentes licences des codes que tu utilise :grin:

oui mais là je fais ca comme un loisirs pour moi pour découvrir et comprendre le fonctionnement, je suis quelqu'un de curieux, ce n'est pas commerciale.
si tu regarde le source qui est sur internet de wc, sur 1000 lignes j'ai du prendre une 20 aine de lignes, et encore je suis obligé de le modifier, car par exemple il n'existe de SAFE_READ dans arduino.
En fait, je me sert surtout des codes source pour m'aider à trouver, comment ils font pour faire cela, après mon code n'a plus rien avoir avec le vrai code sources.

J'ai testé l'exemple plus haut en sortie sur le port serie du terminal il m'affiche la ligne et tous les caractères utf-8 il les transforme avec un point d'interrogation à l'envers.

Alors par contre le terminal FABGL, ne les reconnait pas du tout, je me casse la tête pour rien,
la librairie n'est pas prévu pour du UTF-8, ce qui est logique.

[EDIT]
Sur le terminal FABGL il me remplace les caractères UTF-8 par des caractères ascii mais qui n'ont rien avoir avec le caractère d'origine, mais au moins je peut les afficher sur l'éditeur de texte, sans avoir du griboulli ou des caractères bizarres avec des décalages ou autre.

Oui, si tu ne sais pas où que tu ne gère pas l'utf8 tu ne peut pas savoir que c'en est et si tu gère les caractères spéciaux, il te l'affiche en tant que tel.
Par contre si tu as que des caractères standard en dessous de 128 s'affiche nickels.

Les caractères unicode ce sont ceux qui sont supérieur à 255 ?
Je ne trouve pas de table de caractère unicode en decimal,
Je n'ai que des U+2378 par exemple.
on peut afficher un car. unicode avec la touche Alt ? car sa s'arrête à 255.

Je ne vais pas continuer sur ce problème d'utf8 car dans la doc de FABGL il est bien indiqué qu'il affiche uniquement les caractères ascii.

De plus on ne peut pas changer l'encodage, par exemple ISO-8859 ou UTF-8.

Sous linux ont peu changer l'encodage pour le cat ou more ou less

export LANG="fr_FR.ISO-8859"

Ok donc effectivement pas un souci

L'unicode utilise un entier sur 16 bits, la table ascii standard garde ses valeurs entre 0 et 127 + 127-255 pour l'étendue.
Après les valeurs supérieurs sont les autres tables empilée.
Je crois que c'est assez bien expliqué sur Wikipédia anglais, peut être français.

par rapport à l'UTF8 du coup c'est beaucoup plus consommateur, puisque cela double la mémoire utilisé par rapport au ascii, même si tu utilise les caractère standard latin.

Oui on peut dire cela même si c’est un peu plus compliqué sinon ça ne serait pas marrant :slight_smile:

Pour les curieux :

Au début d’Unicode tout était stocké sur deux octets. Cet encodage, déprécié aujourd’hui, existe toujours. Il se nomme UCS-2 et est de longueur fixe. Il ne permet pas de représenter l’ensemble des caractères Unicode, mais seulement les 65536 premiers, qui sont les plus courants (mais pas d’emojis par exemple).

La plupart des langues latines utilisent que très peu de signe non ASCII et donc il y avait une perte d’espace mémoire alors que pour les langues utilisant des signes ne faisant pas partie de l’ASCII c’était bien pratique.

De plus On savait que le besoin mondial dépasserait la limite de ce qui est représentable sur 16 bits (65536 glyphes) et aujourd’hui le standard Unicode est constitué d'un répertoire contenant un peu moins de 150 000 symboles. Comment est-ce possible si on se limite à 16 bits ?

Le comité à proposé une solution qui convient à tous et en Unicode, la dénomination d’un symbole (son codepoint) et son encodage sont deux choses distinctes.

En pratique il y a une table Unicode gigantesque attribuant un numéro unique à chaque glyph : c’est son codepoint.

Cette table est divisée en 17 plans (de 0 à 16) de deux octets chacun, soit 65 536 points de code par plan.

Ces plans permettent de grouper facilement des symboles et le premier plan (plan 0) est connu sous le nom de Basic Multinlingual Plane (ou BMP) et regroupe les 65536 symboles les plus courants. Les plans de 1 à 16 sont des plans supplémentaires. Unicode peut donc représenter 65 536 x 17 = 1 114 112 glyphes, on est très loin d’avoir saturée la table.

Tous les caractères qui sont en dehors de la BMP n’étaient pas représentables en UCS-2 et c’est pourquoi aujourd’hui cet encodage ne fait plus parti de la norme Unicode.

En échange le consortium a standardisé plusieurs encodages connus sous les noms UTF-n ou n est un nombre. La différence entre ces encodages est la longueur minimale d’octets nécessaires à la représentation d’un caractère.

Par exemple l’UTF-32 est le seul encodage à taille fixe qui ne soit pas déprécié et qui permet de représenter l’intégralité des caractères Unicode sur 32 bits, soit quatre octets glyphe. C’est coûteux mais on a tout avec une taille connue. il n’est presque jamais utilisé pour representer un fichier texte dans votre éditeur mais sert plutôt dans des API de langages de programmation pour avoir un outil uniforme mondial. Python 3 utilise UTF32 pour représenter les variables de texte en mémoire par exemple.

Ensuite il y a deux encodages à taille variables sont dans la norme Unicode, l’UTF-8 et l’UTF-16. Leur maximum est de quatre octets chacun mais la taille minimum d’un glyphe est de un octet en UTF-8 et deux octets en UTF-16.

L’UTF-8 est le plus utilisé aujourd’hui, tant pour le stockage que le transfert d’informations. Sa taille minimale est de huit bits (mais il peut monter jusqu’à quatre octets pour certains signes) et il a la particularité d’être totalement compatible avec l’ASCII et pas sensible au boutisme puisque lisible octet par octet : l’information sur le nombre d’octets nécessaires au codage est contenu dans le premier octet du glyphe.

C’est ce qui a été retenu dan l’IDE arduino et si vous tapez une chaîne dans l’éditeur de code, sa représentation mémoire est en UTF-8. On ne peut donc pas dire qu’il y a 2 octets par symbole, il y en a entre 1 et 4. Ça complique donc un peu la donne car la fonction strlen() retourne le nombre d’octets et pas le nombre de glyphes à l’écran (le symbole € par exemple est sur 2 octets mais occupera l’espace d’un caractère à l’affichage.

Pour être un peu plus complet (si vous avez lu jusqu’ici), en UTF-16 on a donc une longueur variable avec des mots sur 16 bits et un glyphe fait soit deux soit quatre octets. L’UTF-16 n’est pas compatible avec l’ASCII ni avec l’UTF-8 mais rétro-compatible avec l’UCS-2 si on se limite à la BMP, car l’UTF-16 permet d’encoder l’ensemble des caractère de la table Unicode : comme en UCS-2 pour les 65536 premiers sur deux octets et le million de glyphes possibles restants nécessitent l’usage d’un second mot de 2 octets.

En Java et JavaScript, le type String est représenté en interne en UTF-16. Dans ce cadre la méthode length compte le nombre de mots UTF-16 (comme strlen comptait les octets) et si vous êtes au delà de la BMP alors vous aurez aussi une différence entre le nombre de glyphes et la longueur lue.

Oui cela dépend si tu parle de la table de caractère Unicode actuel ou de l'encodage anciennement utilisé dans Dos ou Windows notamment.