1 /******************************************************************************
2 
3  This source file is part of the Avogadro project.
4 
5  Copyright 2013 Kitware, Inc.
6 
7  This source code is released under the New BSD License, (the "License").
8 
9  Unless required by applicable law or agreed to in writing, software
10  distributed under the License is distributed on an "AS IS" BASIS,
11  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  See the License for the specific language governing permissions and
13  limitations under the License.
14 
15  ******************************************************************************/
16 
17 #include "moleculedeserializer.h"
18 
19 #include "matrixserialization.h"
20 #include <avogadro/io/fileformatmanager.h>
21 #include <google/protobuf/io/coded_stream.h>
22 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
23 
24 #include <iostream>
25 
26 using Avogadro::Core::Molecule;
27 using Avogadro::Io::FileFormat;
28 using Avogadro::Io::FileFormatManager;
29 
30 using google::protobuf::io::ArrayOutputStream;
31 using google::protobuf::io::CodedOutputStream;
32 using google::protobuf::io::ArrayInputStream;
33 using google::protobuf::io::CodedInputStream;
34 using google::protobuf::uint32;
35 using google::protobuf::uint8;
36 
37 namespace Avogadro {
38 namespace Core {
39 
MoleculeDeserializer(Molecule * molecule)40 MoleculeDeserializer::MoleculeDeserializer(Molecule* molecule)
41   : m_molecule(molecule)
42 {
43 }
44 
deserialize(const void * data,size_t size)45 bool MoleculeDeserializer::deserialize(const void* data, size_t size)
46 {
47   ArrayInputStream ais(data, size);
48   CodedInputStream cis(&ais);
49 
50   // Read the atoms
51   if (!this->deserializeAtomicNumbers(&cis))
52     return false;
53 
54   // Read the positions2d
55   if (!this->deserializePositions2d(&cis))
56     return false;
57 
58   // Read the positions3d
59   if (!this->deserializePostions3d(&cis))
60     return false;
61 
62   // Read bond pairs
63   if (!this->deserializeBondPairs(&cis))
64     return false;
65 
66   // Read bond orders
67   if (!this->deserializeBondOrders(&cis))
68     return false;
69 
70   return true;
71 }
72 
deserializeAtomicNumbers(google::protobuf::io::CodedInputStream * stream)73 bool MoleculeDeserializer::deserializeAtomicNumbers(
74   google::protobuf::io::CodedInputStream* stream)
75 {
76   // Read the atoms
77   m_molecule->clearAtoms();
78   uint32 numberOfAtoms;
79   if (!stream->ReadLittleEndian32(&numberOfAtoms))
80     return false;
81   for (uint32 i = 0; i < numberOfAtoms; i++) {
82     unsigned char atom;
83     if (!stream->ReadRaw(&atom, sizeof(unsigned char)))
84       return false;
85     m_molecule->addAtom(atom);
86   }
87 
88   return true;
89 }
90 
deserializePositions2d(google::protobuf::io::CodedInputStream * stream)91 bool MoleculeDeserializer::deserializePositions2d(
92   google::protobuf::io::CodedInputStream* stream)
93 {
94   // Get the count
95   uint32 posCount;
96   if (!stream->ReadLittleEndian32(&posCount))
97     return false;
98   // Clear an current positions
99   m_molecule->atomPositions2d().clear();
100   for (uint32 i = 0; i < posCount; i++) {
101     Avogadro::Vector2 vec2;
102     if (!ProtoCall::MatrixSerialization::deserialize(vec2, stream))
103       return false;
104     m_molecule->atomPositions2d().push_back(vec2);
105   }
106 
107   return true;
108 }
109 
deserializePostions3d(google::protobuf::io::CodedInputStream * stream)110 bool MoleculeDeserializer::deserializePostions3d(
111   google::protobuf::io::CodedInputStream* stream)
112 {
113   // Get the count
114   uint32 posCount;
115   if (!stream->ReadLittleEndian32(&posCount))
116     return false;
117   // Clear an current positions
118   m_molecule->atomPositions3d().clear();
119   for (uint32 i = 0; i < posCount; i++) {
120     Avogadro::Vector3 vec3;
121     if (!ProtoCall::MatrixSerialization::deserialize(vec3, stream))
122       return false;
123     m_molecule->atomPositions3d().push_back(vec3);
124   }
125 
126   return true;
127 }
128 
deserializeBondPairs(google::protobuf::io::CodedInputStream * stream)129 bool MoleculeDeserializer::deserializeBondPairs(
130   google::protobuf::io::CodedInputStream* stream)
131 {
132   uint32 bondCount;
133   if (!stream->ReadLittleEndian32(&bondCount))
134     return false;
135 
136   // Clear and bond pairs
137   m_molecule->bondPairs().clear();
138 
139   for (uint32 i = 0; i < bondCount; i++) {
140     uint32 from, to;
141     if (!stream->ReadLittleEndian32(&from))
142       return false;
143     if (!stream->ReadLittleEndian32(&to))
144       return false;
145     std::pair<size_t, size_t> bond;
146     bond.first = from;
147     bond.second = to;
148     m_molecule->bondPairs().push_back(bond);
149   }
150 
151   return true;
152 }
153 
deserializeBondOrders(google::protobuf::io::CodedInputStream * stream)154 bool MoleculeDeserializer::deserializeBondOrders(
155   google::protobuf::io::CodedInputStream* stream)
156 {
157   uint32 bondOrderCount;
158   if (!stream->ReadLittleEndian32(&bondOrderCount))
159     return false;
160 
161   // Clear bond order
162   m_molecule->bondOrders().clear();
163 
164   for (uint32 i = 0; i < bondOrderCount; i++) {
165     unsigned char bond;
166     if (!stream->ReadRaw(&bond, sizeof(unsigned char)))
167       return false;
168 
169     m_molecule->bondOrders().push_back(bond);
170   }
171 
172   return true;
173 }
174 
175 } // namespace Core
176 } // namespace Avogadro
177