Programmation SDIF en C

# LA LIBRAIRIE SDIF

# Documentation du code C

Analyse/Synthèse

Dominique Virolle

- Types de bas niveau, Valeurs et Variables Globales

- Formalisme des noms C dans la librairie SDIF
- Types de bas Niveau

- Dépendances matériel, système, compilateur

- Taille d'une adresse (sizeof(void*))
- Position dans un fichier

- Nombres
- Signature
- type table de hashage

- Constantes Précompilées
- Variables Globales

- Type de Machine gSdifMachineType
- Chaines de caractères de transfert
- Erreurs

- Structure du type SdifFileT

- NameValues
- MatrixTypesTable
- FrameTypesTable
- StreamIDsTable
- Types Prédéfinis

- Lien vers les types prédéfinis

- Structures des types interprétés

- MatrixTypeT
- FrameTypeT
- pseudo-SDIF TextStream

# Types de bas niveau, Valeurs et Variables Globales

- Formalisme des noms C dans la librairie SDIF
- Types de bas Niveau

- Dépendances matériel, système, compilateur

- Taille d'une adresse (sizeof(void*))
- Position dans un fichier

- Nombres
- Signature
- type table de hashage

- Constantes Précompilées
- Variables Globales

- Type de Machine gSdifMachineType
- Chaines de caractères de transfert
- Erreurs

## Formalisme des noms C dans la librairie SDIF

Sauf exceptions, les noms des types, structures, noeuds, listes... suivent ce formalisme:

Mot, Lettre | Définition
--- | ---
S | structure (déclarée par struct).
T | type (déclarée par typedef).
N | noeud (Node), lié à une structure contenant un champ "Next".
L | liste (List), contient un champ "Head" qui est un Node.
E | énumération (déclarée par enum).
HT | table de hashage
_Sdif | précompilé.
e | valeur énuméré par un enum.
g | variable global.
M_ | types de matrice prédéfini.
F_ | types de frame prédéfini.
Sdiff | il y a un argument de type FILE *f.
SdifF | SdifFileT* qui est la structure de plus haut niveau dans la librairie.
U | unsigned.
R et W | Read et Write.
Size | Nombre de bytes (size_t)
Hash | type bas niveau HashTableT*.
Error | détection d'erreur grave (débugage essentiellement).
MatrixType | type de matrice (prédéfini ou utilisateur).
FrameType | type de frame (prédéfini ou utilisateur).
Matrix | bloc de données matrice.
Frame | bloc de données frame.
Test | test d'erreur haut niveau sur un fichier SDIF (SdifFileT).
File | fonctionnalité de haut niveau sur des instances de SdifFileT.
Get et Put | lecture et écriture communes aux fichiers SDIF binaires et aux fichiers pseudo-SDIF textes. Ce sont aussi les lectures et les écritures de certaines structures.
Read et Write | lecture et écriture exclusivement sur fichiers SDIF binaires.
Print | écriture texte. SdifFPrint pour un fichier pseudo-SDIF et SdifPrint pour des sorties sur stdout ou stderr (débugage).
Scan | lecture exclusivement sur fichiers pseudo-SDIF textes.
TextConv | conversion de texte à binaire.
ConvToText | conversion de binaire à texte.
All | tous les éléments d'un certain type dans 1 niveau de structure de fichier SDIF (ex AllMatrix : toutes les matrices d'1 frame).
One | 1 seul élément parmi une succession d'éléments de même sorte.
TimePosition | position disque par rapport au temps.
Create | construction d'un pointeur sur élément.
Kill | destruction d'un pointeur. Dans le cas d'un noeud, la fonction retourne le Next
Num | numéro (identification).
Nb | nombre de... (cardinal).
Head et Tail | 1er et dernier élément d'une liste.
Curr | courant. Cela peut-être un noeud, une signature, une entête de bloc...
iAAA | ième AAA (compteur)

## Types de bas Niveau

### Dépendances matériel, système, compilateur

#### Taille d'une adresse (sizeof(void*))

La seule dépendance liée au matériel ou au système indiquée par un `#ifdef` est la taille d'une adresse. La librairie fonctionne sur les OS 32 et 64 bits (16 bits non prévu). On a ainsi:

    /* dans SdifRWLowLevel.h*/
    #if defined(__mips64) || defined(__alpha)
    #define _LONG64BITS_
    #else
    #define _LONG32BITS_
    #endif

#### Position dans un fichier

Il y a une dépendance sur le compilateur au niveau du type C `fpos_t`. Certains compilateurs ont `fpos_t` défini comme un `long`. Pour d'autres, `fpos_t` est une structure; on ne peut donc pas faire simplement des opérations arithmétiques directement sur les variables (ex : Macintosh MacOS8, CodeWarrior 10).
Dans SdifGlobals.h, on a un faux (précompilé) type SdifFPosT qui permet d'avoir la position d'un fichier codé sur un long. La taille de de ce type dépend donc du système : sur IRIX 5.3, Macintosh... c'est 4 bytes, et sur IRIX64 et Alpha on a 8 bytes. Les fonctions de positionnement sont donc toujours associés au système automatiquement (pas de réduction de 8 bytes à 4 bytes sur les machines 64 bits).

    /* SdifGlobals.h  fpos_t compatible sur Macintosh */
    #ifdef MACINTOSH
    #define SdifFPosT long
    #define SdifFGetPos(f,p)    ((((*(p)) = ftell(f)) == -1) ? -1 : 0)
    #define SdifFSetPos(f,p)    fseek(f, (*(p)), SEEK_SET)
    #else
    #define SdifFPosT fpos_t
    #define SdifFGetPos(f,p)    fgetpos((f),(p))
    #define SdifFSetPos(f,p)    fsetpos((f),(p))
    #endif

### Nombres

SdifGlobals.h : Sont définis des types de très bas niveau représentant les `int`, `float` (`unsigned`) sur 2, 4, 8 bytes. Cela sous-entend que le matèriel satisfasse :

- sizeof(short) == 2,
- sizeof(int) == 4,
- sizeof(float) == 4,
- sizeof(double) == 8.

La librairie SDIF ne fait pas la vérification de ces égalités mais elles sont en général vraies pour des OS 32 et 64 bits.

On a ainsi les types:

    typedef short          SdifInt2;
    typedef unsigned short SdifUInt2;
    typedef int            SdifInt4;
    typedef unsigned int   SdifUInt4;
    typedef float          SdifFloat4;
    typedef double         SdifFloat8;

Est associé aux différents types de bas niveau, un type d'énumération qui permet de représenter les différents types avec un codage sur 4 bytes.

- Le premier byte représente une sémantique:

- 0x0 : `float`,
- 0x1 : `int`,
- 0x2 : `char`

- Le second indique si le type est signé:

- 0x0 : `signed`,
- 0x1 : `unsigned`

- Les deux autres bytes donne le nombre de bits de la donnée

- 0x10 : 16 bits,
- 0x20 : 32 bits,
- 0x40 : 64 bits

    typedef enum SdifDataTypeE
    {
      eFloat4 = 0x20,
      eFloat8 = 0x40,
      eInt2   = 0x1010,
      eUInt2  = 0x1110,
      eInt4   = 0x1020,
      eUInt4  = 0x1120,
      eChar4  = 0x2020
    } SdifDataTypeET;

### Signature

Toujours dans SdifGlobals.h, est défini le type SdifSignature. Une signature étant un mot de 4 bytes, les signatures sont représentées par un `unsigned int`. Est associée à ce type une énumération des signatures de base, qui sont celles des chunks spéciaux. Les types de frames et de matrices prédéfinis n'y sont pas car tous les types de données sont interprétés et évolutifs.

    typedef unsigned int   SdifSignature;
    typedef enum SdifSignatureE
    {
      eSDIF = 'SDIF' ,         /* SDIF header */
      e1NVT = '1NVT' ,         /* Name Value Table */
      e1TYP = '1TYP' ,         /* TYPe declarations */
      e1MTD = '1MTD' ,         /* Matrix Type Declaration */
      e1FTD = '1FTD' ,         /* Frame Type Declaration */
      e1IDS = '1IDS' ,         /* ID Stream Table */
      eSDFC = 'SDFC' ,         /* Start Data Frame Chunk (text files) */
      eENDC = 'ENDC' ,         /* END Chunk (text files) */
      eENDF = 'ENDF' ,         /* END File (text files) */
      eFORM = 'FORM' ,         /* FORM for IFF compatibility (obsolete ?) */
      eEmptySignature = '\0\0\0\0'
    } SdifSignatureET;

Quelques fonctions sont directements liées aux signatures:

    #define _SdifNbMaxPrintSignature 8
    char  gSdifStringSignature[_SdifNbMaxPrintSignature][5];

    char* SdifSignatureToString(SdifSignature Signature);
    short SdifSignatureCmpNoVersion(SdifSignature Signature1, SdifSignature Signature2);

`SdifSignatureToString` permet de renvoyer un pointeur sur une chaine de caractères contenant les caractères de la signature passée en argument avec un caractère de fin de chaine. Ce pointeur est directement utilisable avec les fonctions de sorties standarts formatées. `_SdifNbMaxPrintSignature` (8) et `gSdifStringSignature` servent uniquement à cette fonction. `gSdifStringSignature` est un tableau de 8 chaines de caractères, chacune de taille 5. `SdifSignatureToString` utilise ce tableau de façon cyclique pour son résultat. On évite ainsi de s'occuper de la mémoire pour ces convertions de signature en chaine de caractères. Toutefois, on ne peut pas utiliser `SdifSignatureToString` plus de 8 fois dans les paramètres d'une fonctions. On ne pourra pas afficher 9 signatures avec la même instruction `printf`. La première affichié serait la 9ième car c'est la même position mémoire. Actuellement, aucune utilisation de `SdifSignatureToString` n'a dépassée 2 signatures sur une même instruction..

`SdifSignatureCmpNoVersion` permet de comparer 2 signatures sans le premier byte. Ainsi on peut tenter des lectures sur des matrices ou des frames de version inconnu par le programme lecteur (la librairie doit tout de même connaître les signatures).

### type table de hashage

SdifHash.h
SdifHash.c

`SdifHashIndexUnion` est un type qui permet de définir le type d'index d'une table de hashage. On peut en effet avoir des tables indexée par des chaînes de caratères (méthode classique) et d'autres directement par des entiers. Le type est défini par un `union` qui est soit un `unsigned int` sur 4 bytes soit un tableau de 1 pointeur sur un chaine de caractère. La représentation sous forme de tableau sert uniquement à fixer la taille d'une variable de `SdifHashIndexUnion` à 4 bytes (ou 8 si la machine est 64 bits comme Dec Alpha).

    typedef union SdifHashIndexU
    {
      char* Char[1]; /* tab of one pointer to fixe union size at 4 or 8 bytes */
      unsigned int  Int4;
    } SdifHashIndexUT;

`SdifHashIndexTypeEnum` est un `enum` qui permet de dire quel type de l'`union` est utilisé dans une table de hashage.

    typedef enum SdifHashIndexTypeE
    {
      eHashChar,
      eHashInt4
    } SdifHashIndexTypeET;

Le type table de hashage est défini comme suit:

    typedef struct SdifHashNS SdifHashNT;

    struct SdifHashNS
    {
      SdifHashNT *Next;
      SdifHashIndexUT Index;
      void* Data;
    };

    typedef struct SdifHashTableS
    {
      SdifHashNT* *Table;
      unsigned int HashSize;
      SdifHashIndexTypeET IndexType;
      void (*Killer)();  /* no verification of arguments */
      unsigned int NbOfData;
    } SdifHashTableT;

Le champ `Table` est un pointeur sur un tableau de noeuds de donnée hashée `SdifHashNT`. Le champ `Data` du noeud n'est pas typé. C'est à dire que l'on peut créer des tables de hashages contenant des objets de type quelconque. Mais pour une table de hashage donnée, tous les objets sont de même type et de même allocation (statique ou dynamique).
Le seul champ du type `SdifHashTableT` contenant une information sur le type de données de la table est `Killer` qui est un pointeur sur la fonction de destruction associée. Dans le cas d'une table à données statiques, `Killer` doit être `NULL`. Les tables de hashages sont souvent utilisées dans la librairie. Les fichiers SdifHash.* n'utilisent aucunes informations des autres fichiers.

La taille d'une table de hashage doit être un nombre premier. C'est le cas de beaucoup de nombres (2^n - 1).

## Constantes Précompilées

Token | Valeur | Fichier | Définition
--- | --- | --- | ---
_SdifUnknownSize | 0xffffffff | SdifGlobals.h | Valeur donnée à un champ indiquant une taille de bloc inconnue.
_SdifPadding | 8 | SdifGlobals.h | Nombre de bytes d'alignement : 8 bytes => alignement sur 64 bits.
_SdifFloat8Error | 0xffffffff | SdifGlobals.h | Retour erronée de lecture d'un float (à modifier).
_SdifStringLen | 1024 | SdifGlobals.h | Taille d'une chaine de caractère à memoire statique
_SdifTypesFileName | "SdifTypes.STYP" | SdifGlobals.h | Nom du fichier contenant la base de données des types prédéfinis
_SdifBSLittleE | 4096 | SdifRWLowLevel.h | Taille du buffer maximum pour les lectures, écritures binaires sur fichier.
_SdifPaddingChar | '\0' | SdifRWLowLevel.h | Caractère utilisé pour le Padding
_SdifReservedChars | `",;{}[]:"` | SdifRWLowLevel.h | Chaine de caractères contenant les caractères résevés de Sdif
_SdifFrameHeaderSize | 24 | SdifFrame.h | Taille de l'entête d'un frame (constant pour le format).
_SdifGenHashSize | 127 | SdifGlobals.h | Taille des tables de hashage globales (doit être un nombre premier)
_SdifNameValueHashSize | 31 | SdifNameValue.h | Taille des tables de hashage d'informations
_SdifGranule | 1024 | SdifGlobals.h | Taille des blocs d'allocation pour le type SdifOneRowT
_SdifFloatEps | 1.0e-20 | SdifGlobals.h | Valeur epsilon floattante

## Variables Globales

### Type de Machine gSdifMachineType

Le type de la machine (BigEndian ou LittleEndian) est détermineé par la librairie SDIF à l'exécution d'un programme et non en précompilation des sources SDIF. Ainsi, on a une variable globale `gSdifMachineType` accessible partout. Sa valeur est d'un type énuméré `SdifMachineEnum` qui propose plusieurs type de machines (SdifRWLowLevel.h). Une fois que cette variable est affectée, il n'est plus nécessaire de la modifier. La fonction assiociée à la détermination du type de machine est `SdifMachineEnum SdifGetMachineType(void)`.

    typedef enum SdifMachineE
    {
      eUndefinedMachine,
      eBigEndian,
      eLittleEndian,
      eBigEndian64,
      eLittleEndian64,
      ePDPEndian
    } SdifMachineET;

    extern SdifMachineET gSdifMachineType;

    extern SdifMachineET SdifGetMachineType(void);
    extern SdifMachineET SdifInitMachineType(void);

### Chaines de caractères de transfert

Il est souvent nécessaire de lire ou d'écrire des chaines de caractères dans un fichier et de les recopier dans des pointeurs de `char` alloués à la taille ajustée.

    extern char gSdifString[_SdifStringLen];
    extern char gSdifString2[_SdifStringLen];
    extern char gSdifErrorMess[_SdifStringLen];

`gSdifString` et `gSdifString2` sont utilisées pour les lectures essentiellement. Elle sont déclarées en taille statique (`_SdifStringLen == 1024`).
`gSdifErrorMess` est déclarée comme les précédentes mais est utilisée exclusivement pour les constructions de messages d'erreur par des `sprintf`.

### Erreurs

SdifError.h
SdifError.c

     typedef enum SdifErrorE
    {
      eFalse = 0,
      eTrue = 1,
      eFreeNull = 256,
      eAllocFail,
      eArrayPosition,
      eEof,
      eFileNotFound,
      eInvalidPreType,
      eAffectationOrder,
      eNoModifErr,
      eNotInDataTypeUnion,
      eNotFound,
      eExistYet,
      eWordCut,
      eTokenLength
    } SdifErrorEnum;

Il s'agit des erreurs dont la detection implique souvent une erreur de programmation (Sauf pour les erreurs sur fichiers). Elles provoquent souvent une sortie violante `exit(1)`. `eFalse` et `eTrue` ne sont qu'une autre représentation de 0 ou 1. Les erreurs d'interprétation des fichiers dûes par exemple à un type non défini sont gérées par les tests de haut niveau (SdifTest.*).

# Structure du type SdifFileT

- NameValues
- MatrixTypesTable
- FrameTypesTable
- StreamIDsTable
- Types Prédéfinis

- Lien vers les types prédéfinis

La librairie permet de contrôler plusieurs fichiers SDIF en lecture ou écriture simultanément. Ils sont représentés par une structure de haut niveau `SdifFileS` défini dans SdifFileStruct.h. Ils ont en commun la base des types prédéfinis (qui est elle-même considérée comme une structure SdifFileT). Ils ont chacun :

- Un nom de fichier SDIF (même s'il n'existe pas physiquement).
- Une liste de tables de Name Values (NameValues).
- Une table des types de matrices utilisées (MatrixTypesTable).
- Une table des types de frames utilisées (FrameTypesTable).
- Une table (liste) de Stream ID (StreamIDsTable).
- Un flot SDIF binaire de lecture ou d'écriture (Stream).
- Un flot pseudo-SDIF text (TextStream) associé à un nom (TextStreamName).
- Un mode d'ouverture: écriture, lecture ou lecture texte seulement (Mode).
- Une signature courante (CurrSignature).
- Une entête de frame courante (CurrFramH).
- Une entête de matrice courante (CurrMtrxH).
- Une ligne de donnée courante (CurrOneRow).

Le principe de la structure `SdifFileS` est de considérer:

- les tables comme une base de données (bdd) des informations d'entête du fichier,
- Stream comme le fichier SDIF binaire,
- TextStream comme le fichier de transfert de SDIF en texte ou de texte en SDIF.

La bdd permet de récupérer des paramètres ou d'en ajouter à tout moment, independamment du fichier sur disque. Les deux flots, un binaire, un texte permet de conserver une identité forte sur le fichier binaire et de réaliser des conversions de façon simple.

## NameValues

`SdifNameValuesLT* NameValues`
Liste de tables de hashage de type `SdifHashTableT*`, où chaque table correspond à un chunk d'informations.

L'indexation des tables est par le nom de l'information et les données sont du type `SdifNameValueT*` dont le destructeur est `SdifKillNameValue(*)`. La taille de chaque petite table d'information est `_SdifNameValueHashSize`.

## MatrixTypesTable

`SdifHashTableT* MatrixTypesTable`
Table contenant tout les types de matrices associées à un fichier.

L'indexation de la table est par un entier représentant le hashage de la signature. Les données de cette table sont de type `SdifMatrixTypeT*` dont le destructeur est `SdifKillMatrixType(*)` (SdifMatrixType.*).

## FrameTypesTable

`SdifHashTableT* FrameTypesTable`
Table contenant tout les types de frames associés à un fichier.

L'indexation de la table est par un entier représentant le hashage de la signature. Les données de cette table sont de type `SdifFrameTypeT*` dont le destructeur est `SdifKillFrameType(*)` (SdifFrameType.*).

## StreamIDsTable

`SdifHashTableT* StreamIDsTable`
Table contenant tous les Stream IDs associés à un fichier.

L'indexation est par l'entier `numID` des Stream IDs. La taille de la table de hashage est 1, donc il y a continuellement colision, il s'agit ainsi d'une liste triée par les IDs. Ceci uniquement pour que les fichiers SDIF est ses Stream IDs triés. Aussi, pour des renumérotations des IDs, on pourrait préférer cette structure triée.

Les données de la table sont de type `SdifStreamIDT*` dont le destructeur est `SdifKillStreamID(*)` (SdifStreamID.*).

## Types Prédéfinis

Variable globale: `SdifFileT *gSdifPredefinedTypes`
Les types prédéfinis de SDIF sont interprétés par la librairie au même titre que les types spécifiques à un fichier. Ceci pour deux raisons:

- Les types spécifiques peuvent être des complétions des types prédéfinis.
- Interpréter les types prédéfinis en lisant un fichier texte permet à l'adminitrateur de la librairie d'ajouter de nouveaux types prédéfinis de façon très simple, sans recompiler la librairie.

Ainsi `gSdifPredefinedTypes` est une instance (pointeur) de SdifFileT dont le mode d'ouverture est la lecture texte seulement. `Stream` est donc fermé et `TextStream` est ouvert en lecture le temps du chargement. Si le fichier texte contenant les types prédéfinis est introuvable, alors la librairie charge les types précodés statiquement dans SdifPreType.*. Dans ce cas un message sur `stderr` indique que la base des types prédéfinis peut être incomplète.

### Lien vers les types prédéfinis

La liaison entre `gSdifPredefinedTypes` et les autres fichiers se fait à partir des types (C) `SdifMatrixTypeT` et `SdifFrameTypeT` dont les structures contiennent un lien ("Pre") sur les types prédéfinis. Dans `gSdifPredefinedTypes` les type sont tous dans les listes "Use" et les liste "Pre" sont vides. La mise à jour des liens ce fait ainsi:

    /* SdifF est un pointeur sur SdifFileT.
     * Signature est la signature du type de matrice.
     * SdifGetMatrixType(SdifF->MatrixTypesTable, Signature) ne recherche le type
     * que dans la table des types de matrices de SdifF et non dans celle
     * de gSdifPredefinedTypes.
     * Si le type n'existe pas déjà, alors on le recherche dans
     * gSdifPredefinedTypes->MatrixTypesTable. Si on le trouve, alors
     * on crée un type de matrice en donnant le type predefini en 2ième
     * argument de SdifCreateMatrixType puis on ajoute le type à la table de SdifF.
     */

    if (! SdifGetMatrixType(SdifF->MatrixTypesTable, Signature))
      {
        if (PredefinedMatrixType = SdifGetMatrixType(gSdifPredefinedTypes->MatrixTypesTable, Signature))
          {
            SdifCreateMatrixType(Signature, PredefinedMatrixType);
            SdifPutMatrixType(SdifF->MatrixTypesTable, MatrixType);
          }
        else
          ; /* le type n'existe pas */
      }
    else
      ; /* le type existe déjà */

    /* idem pour les types de frame avec SdifGetFrameType et SdifPutFrameType.
     */

# Structures des types interprétés

- MatrixTypeT
- FrameTypeT
- pseudo-Sdif TextStream

## MatrixTypeT

    typedef struct SdifColumnDefS
    {
      char *Name;
      SdifUInt4 Num;
    } SdifColumnDefT;

    typedef struct SdifColumnDefNS SdifColumnDefNT;

    struct SdifColumnDefNS
    {
      SdifColumnDefNT *Next;
      SdifColumnDefT *ColumnDef;
    };

    typedef struct SdifMatrixTypeS SdifMatrixTypeT;

    struct SdifMatrixTypeS
    {
      SdifSignature      Signature;

      SdifMatrixTypeT    *MatrixTypePre;

      SdifColumnDefNT *HeadUse;
      SdifColumnDefNT *TailUse;
      SdifUInt4       NbColumnDefUse;

      SdifUInt4       NbColumnDef;
      SdifModifModeET ModifMode;
    };

Un type de matrice est défini comme une signature associée à deux listes dont la concaténation est la suite des colonnes d'un bloc matrice. La première est la liste des colonnes du type prédéfini s'il existe. La seconde est la liste des colonnes de complétion.

Ainsi `MatrixTypePre` est le lien sur le type prédéfini qu'il faut mettre à jour à la rencontre de la signature dans les fichiers Stream ou Stream ou lors d'ajout "manuel" de colonnes en complétion. Ce lien est `NULL` s'il n'y a pas de type prédéfini pour la signature considérée.(cf. Lien vers les types prédéfinis)

`HeadUse` et `TailUse` sont des acces sur les colonnes de complétion. Ainsi on retrouve toutes les colonnes d'un type de matrice en parcourant `MatrixTypePre->HeadUse` jusqu'à `MatrixTypePre->TailUse` puis `HeadUse` jusqu'à `TailUse`. NbColumnDef est le nombre total de colonnes du type de matrice.

La contruction des listes de colonnes se fait par insertion à la queue pour respecter l'ordonnancement des colonnes imposé par la norme.

## FrameTypeT

    typedef struct SdifComponentS
    {
      SdifSignature MatrixSignature;
      char *Name;
      SdifUInt4  Num;
    } SdifComponentT;

    typedef struct SdifComponentNS SdifComponentNT;
    struct SdifComponentNS
    {
      SdifComponentNT *Next;
      SdifComponentT *Component;
    };

    typedef struct SdifFrameTypeS SdifFrameTypeT;
    struct SdifFrameTypeS
    {
      SdifSignature Signature;

      SdifFrameTypeT* FrameTypePre;

      SdifComponentNT *HeadUse;
      SdifComponentNT *TailUse;
      SdifUInt4       NbComponentUse;

      SdifUInt4       NbComponent;
      SdifModifModeET ModifMode;
    };

Les types de frames fonctionnent comme les types de matrices. Un type de frames étant une signature associée à des composants réparties en deux listes, celle du type de frame prédéfini `FrameTypePre->HeadUse` et celle du type de frame local `HeadUse`.

Les composants sont une signature de type de matrice, et un nom. Il est donc nécessaire de mettre à jour les types de matrice, c'est à dire créer le lien vers le type prédéfini s'il existe, lorsque l'on ajoute un nouveau composant au type de frame.(cf. Lien vers les types prédéfinis)

## pseudo-SDIF TextStream

Pour pouvoir créer manuellement et lire des fichiers SDIF, la librairie possède une gestion d'un format pseudo-SDIF texte. Toutes les données d'un fichier SDIF sont convertibles en texte exceptés les tailles de chunks. Les chunks ASCII ont un contenu identique pour les fichiers SDIF binaires et les fichiers texte

``