2010-05-18 6 views
5

je dois ajouter une sorte de fonctionnalité d'archivage à une mise en œuvre Objective-C Trie (NDTrie sur github), mais j'ai très peu d'expérience avec C et il est des structures de données.struct sérialisation avec des pointeurs vers NSData

struct trieNode 
{ 
    NSUInteger key; 
    NSUInteger count, 
    size; 
    id object; 
    __strong struct trieNode ** children; 
    __strong struct trieNode * parent; 
}; 

@interface NDTrie (Private) 
- (struct trieNode*)root; 
@end 

Ce que je besoin est de créer un NSData avec la structure de l'arbre de cette racine - ou linéariser/désérialiser l'arbre entier d'une autre manière (? Conforme à NSCoding), mais je n'ai pas la moindre idée comment travailler avec NSData et une structure C contenant des pointeurs.

Performance sur désérialisation l'objet résultant serait crucial, car cela est un projet iPhone et je besoin de le charger en arrière-plan à chaque fois que l'application commence.

Quel serait le meilleur moyen d'y parvenir?

Merci!

Répondre

1

En supposant que vous devez tenir à C droite, parce que c'est la façon dont les choses sont déjà configurés, ce que vous devez faire est en fait assez simple .

Il suffit d'écrire une fonction C pour écrire votre arbre sur le disque, avec une hypothèse sur la commande (par exemple, vous écrivez notre profondeur d'abord, de gauche à droite). Pour tous les objets Objective-C, les encoder dans NSData et écrire la taille et les octets de ceux-ci dans le cadre de votre flux.

Quand vous lisez les données de retour dans, reconstruisent simplement l'arbre en fonction de vos hypothèses de commande, et mettre en place les pointeurs vers les enfants. Désarchivez tous les objets Objective-C incorporés, le cas échéant. Vous pouvez probablement le faire avec NSCoder d'une façon ou d'une autre, mais il serait plus facile de faire la reconstruction de l'arbre en dehors de cela, car vous pouvez recopier l'arbre en passant les arguments que vous voulez, ce qui n'est pas très facile avec NSCoding.

J'ai un code (bureau OS X) qui fait quelque chose de très semblable à cela, sans les objets incorporés, mais il est assez délicat, et je ne peux pas poster. Une optimisation dans ce code consiste à lire dans les données dans un tampon interne, en morceaux MB (plutôt qu'un petit nombre d'octets à la fois, pour chaque struct), puis lire les données de ce tampon, bien que Je ne suis pas sûr que cela ait jamais été référencé, et cela peut ou non faire une différence significative sur l'iPhone en tout cas. On dirait qu'il ya une optimisation similaire pour l'écriture aussi bien, qui est plus susceptible d'être une victoire, si je comprends bien (iPhone écrit sont chers, ou alors je l'ai entendu).

0

Vous devez toujours essayer la voie facile d'abord:

// serializing: 
[myTrie writeToFile:myPath atomically:NO]; 

// deserializing 
NDTrie* myTrie = [NDTrie trieWithContentsOfFile:myPath]; 

Si c'est vraiment pas assez rapide, vous pouvez regarder dans sérialisation manuellement les struct sous-jacents.

Edit:

Vous avez fait clair que la quantité de données nécessite une mise en œuvre optimisée.

Je propose de réécrire le struct trieNode et l'accès à des méthodes d'utiliser des indices au lieu des pointeurs pour les parent et children champs. Les indices pointeraient dans un grand tableau C de structures de trieNode, d'où tous les nœuds sont alloués.

Ce tableau de type C peut être maintenue dans un objet NSData dans l'emballage objet NDTrie. La sérialisation et la désérialisation signifieraient alors simplement sauvegarder/charger l'objet NSData (problèmes d'endianess mis à part).

+0

Le problème est mon ensemble de données est assez grand, et en ce moment je ne peux pas l'adapter à la fois la NSArray temporaire et la structure de données arborescente réelle sur la mémoire de l'appareil - aussi il est tout simplement trop lent pour créer deux structures. C'est pourquoi je cherchais un moyen d'ignorer cette recréation et de sérialiser le modèle réel. – leolobato

2

réimplémentons la structure de nœud d'arbre comme un objectif de classe C. par exemple. Ensuite, vous pouvez utiliser le mécanisme standard Objective-C pour archiver et désarchiver ces objets. Vous pouvez ensuite utiliser le mécanisme standard d'Objective-C pour archiver et désarchiver ces objets.

Si après la mise en œuvre du ci-dessus et le profilage de votre code, vous trouvez que les performances sont un problème, vous pouvez commencer à optimiser. Par exemple, en accédant à ivars en utilisant la structure de pointeur C struct, par ex.

aTrieNode->parent; 

ou en remplaçant le NSArray avec un tableau C, etc.

+0

Le problème est que je dois à peu près réécrire toute implémentation existante d'utiliser une classe au lieu de cette struct - c'est pourquoi je suis à la recherche d'un moyen de sérialisation struct existant, il devrait être beaucoup plus rapide à mettre en œuvre. – leolobato

+0

Il ne me semble pas y avoir beaucoup de choses. C'est seulement un fichier source et vous trouverez probablement des choses simplifiées si vous utilisez une classe. Je pourrais y aller moi-même ... – JeremyP

0

Je pense que vous mettre en œuvre le protocole NSCoding qui devraient: dans votre initWithCoder: créer un NSArray avec tous children et réallouer un tel tableau de struct en encodeWithCoder:.

De cette façon, vous serez en mesure d'utiliser le tableau original de struct dans le reste du projet.

Questions connexes