[Qt-interest] How to deal with pointers for a QDataStream?

Andre Somers andre at familiesomers.nl
Tue Apr 20 13:43:01 CEST 2010


On 20-4-2010 12:14, Oliver Heins wrote:
> Hi André,
>
> Andre Somers<andre at familiesomers.nl>  writes:
>
>    
>> On 19-4-2010 14:41, Oliver Heins wrote:
>>      
>>> I have a data structure which holds some pointers:
>>>
>>> class Token
>>> {
>>> public:
>>>       enum Type { Space, Paragraph, Kern, Char, Format, Note, End };
>>>       enum SubType { Bold, Italic,
>>>                      Header1, Header2, Header3, Header4, Header5, Header6,
>>>                      Itemize, Enumerate, Description, Item,
>>>                      Note1, Note2, Note3, Note4, Note5 };
>>>
>>>       [...]
>>>
>>>       Type type;
>>>       SubType subType;
>>>       QChar chr;
>>>       Token *parent;
>>>       QLinkedList<Token *>   children;
>>>       Token *partner;
>>> };
>>>
>>> As saving pointers directly to a QDataStream will obviously not work,
>>> what would be a good strategy to save the structure?
>>>
>>>
>>>        
>> One way is to give each item you need to store a pointer to an ID that
>> is unique for the file (if such a thing is not already there), and
>> store these ID's instead of the pointers to the objects. On loading,
>> you can reconstruct the pointers by using the ID's to lookup the
>> addresses from some (temporary?) data structure such as a QHash<int,
>> Token*>  that you keep around at loading time.
>>      
> Thanks, that's the way I intent to go.  However, I run into another
> problem: The data I write is not read properly.
>
> This is how I go: I write my MagicNumber and the highest unique id to
> the file.  Then I traverse my QLinkedList<Token*>, writing the tokens:
>
>      while (i.hasNext())
>          out<<  *(i.next());
>
> On reading, MagicNumber and the max id are set properly.  Then I try to
> read the data into a QVector<Token>  tokenVec:
>
>      in>>  tokenVec;
>    
Huh? You are writing the data away with a loop, but expect to be able to 
read them back in one go into a QVector? That seems a bit optimistic... 
QVector itself has a structure, as documentented in the page "Format of 
the QDataStream Operators" in the documentation. It first writes out a 
32 bits unsigned integer with the number of elements, and then the 
elements themselves. If you don't have that number of elements writen 
out, how do you expect QVector to be able to properly stream in the data?
> But the Tokens get filled with garbage.  This is how the<<  and>>
> operators are defined:
>
> QDataStream&operator<<(QDataStream&out, const Token&token)
> {
>      quint32 partner = token.partner ? token.partner->unique : 0;
>      quint32 parent = token.parent ? token.parent->unique : 0;
>
>      out<<  qint16(token.type)<<  qint16(token.subType)<<  token.chr
>          <<  quint32(token.unique)<<  parent<<  partner;
>      return out;
> }
>
> QDataStream&operator>>(QDataStream&in, Token&token)
> {
>      quint32 partner, parent;
>      qint16 type, subType;
>
>      token.parent = 0;
>      token.partner = 0;
>      in>>  type>>  subType>>  token.chr>>  token.unique>>  parent>>  partner;
>      token.type = static_cast<Token::Type>(type);
>      token.subType = static_cast<Token::SubType>(subType);
>
>      return in;
> }
>
> What is going wrong here?
>    
Is token.unique actually a quint32? You stream it out as one, but I can 
not see if is streamed in properly based on this code. And what is 
token.chr exactly?

By the way: don't forget to handle the version of your QDataStream 
properly! It changes between Qt releases. If you leave it implicit, you 
may end up not being able to read back your old files with a new release 
of your software... See QDataStream::setVersion.

André




More information about the Qt-interest-old mailing list