@@ -248,6 +248,126 @@ int Graph<T>::readFromMTXFile(const std::string &workingDir,
248248 return 0 ;
249249}
250250
251+ template <typename T>
252+ int Graph<T>::readFromBinaryFile(const std::string &workingDir,
253+ const std::string &fileName,
254+ bool readNodeFeatures, bool readEdgeWeights) {
255+ std::string filepath = workingDir + " /" + fileName + " .bin" ;
256+ return readFromBinary (filepath, readNodeFeatures, readEdgeWeights);
257+ }
258+
259+ template <typename T>
260+ int Graph<T>::readFromBinary(const std::string &filepath, bool readNodeFeatures,
261+ bool readEdgeWeights) {
262+ std::ifstream in (filepath, std::ios::binary);
263+ if (!in.is_open ()) {
264+ return -1 ;
265+ }
266+
267+ try {
268+ // Read and verify header
269+ uint32_t magic;
270+ in.read (reinterpret_cast <char *>(&magic), sizeof (magic));
271+ if (magic != BINARY_MAGIC_NUMBER) {
272+ return -2 ; // Invalid file format
273+ }
274+
275+ uint32_t version;
276+ in.read (reinterpret_cast <char *>(&version), sizeof (version));
277+ if (version != BINARY_VERSION) {
278+ return -3 ; // Unsupported version
279+ }
280+
281+ uint64_t numNodes, numEdges, flags;
282+ in.read (reinterpret_cast <char *>(&numNodes), sizeof (numNodes));
283+ in.read (reinterpret_cast <char *>(&numEdges), sizeof (numEdges));
284+ in.read (reinterpret_cast <char *>(&flags), sizeof (flags));
285+
286+ bool hasNodeFeatures = (flags & BINARY_FLAG_HAS_NODE_FEATURES) != 0 ;
287+ bool hasEdgeWeights = (flags & BINARY_FLAG_HAS_EDGE_WEIGHTS) != 0 ;
288+
289+ // Read nodes
290+ std::unordered_map<std::string, shared<Node<T>>> nodeMap;
291+ for (uint64_t i = 0 ; i < numNodes; ++i) {
292+ std::string nodeId = readBinaryString (in);
293+
294+ T nodeData{};
295+ if (hasNodeFeatures && readNodeFeatures) {
296+ uint32_t dataSize;
297+ in.read (reinterpret_cast <char *>(&dataSize), sizeof (dataSize));
298+
299+ if (dataSize > 0 && is_binary_serializable<T>::value) {
300+ in.read (reinterpret_cast <char *>(&nodeData), sizeof (T));
301+ }
302+ } else if (hasNodeFeatures) {
303+ // Skip node data if present but not reading
304+ uint32_t dataSize;
305+ in.read (reinterpret_cast <char *>(&dataSize), sizeof (dataSize));
306+ if (dataSize > 0 ) {
307+ in.seekg (dataSize, std::ios::cur);
308+ }
309+ } else {
310+ uint32_t dataSize;
311+ in.read (reinterpret_cast <char *>(&dataSize), sizeof (dataSize));
312+ }
313+
314+ auto node = std::make_shared<Node<T>>(nodeId, std::move (nodeData));
315+ nodeMap[nodeId] = node;
316+ }
317+
318+ // Read edges
319+ for (uint64_t i = 0 ; i < numEdges; ++i) {
320+ std::string edgeId = readBinaryString (in);
321+ std::string node1Id = readBinaryString (in);
322+ std::string node2Id = readBinaryString (in);
323+
324+ uint8_t edgeFlags;
325+ in.read (reinterpret_cast <char *>(&edgeFlags), sizeof (edgeFlags));
326+
327+ bool isDirected = (edgeFlags & 0x01 ) != 0 ;
328+ bool isWeighted = (edgeFlags & 0x02 ) != 0 ;
329+
330+ double weight = 0.0 ;
331+ if (hasEdgeWeights && isWeighted) {
332+ if (readEdgeWeights) {
333+ in.read (reinterpret_cast <char *>(&weight), sizeof (weight));
334+ } else {
335+ in.seekg (sizeof (double ), std::ios::cur);
336+ }
337+ }
338+
339+ auto node1 = nodeMap[node1Id];
340+ auto node2 = nodeMap[node2Id];
341+
342+ shared<Edge<T>> edge;
343+ if (isDirected) {
344+ if (isWeighted && readEdgeWeights) {
345+ edge = std::make_shared<DirectedWeightedEdge<T>>(edgeId, node1, node2,
346+ weight);
347+ } else {
348+ edge = std::make_shared<DirectedEdge<T>>(edgeId, node1, node2);
349+ }
350+ } else {
351+ if (isWeighted && readEdgeWeights) {
352+ edge = std::make_shared<UndirectedWeightedEdge<T>>(edgeId, node1,
353+ node2, weight);
354+ } else {
355+ edge = std::make_shared<UndirectedEdge<T>>(edgeId, node1, node2);
356+ }
357+ }
358+
359+ this ->addEdge (edge);
360+ }
361+
362+ in.close ();
363+ return 0 ;
364+
365+ } catch (const std::exception &e) {
366+ in.close ();
367+ return -4 ;
368+ }
369+ }
370+
251371template <typename T>
252372int Graph<T>::readFromDot(const std::string &workingDir,
253373 const std::string &fileName) {
@@ -436,5 +556,15 @@ void Graph<T>::recreateGraph(
436556 }
437557}
438558
559+ // Helper function to read string with length prefix
560+ template <typename T>
561+ std::string Graph<T>::readBinaryString(std::ifstream &in) const {
562+ uint32_t len;
563+ in.read (reinterpret_cast <char *>(&len), sizeof (len));
564+ std::string str (len, ' \0 ' );
565+ in.read (&str[0 ], len);
566+ return str;
567+ }
568+
439569} // namespace CXXGraph
440- #endif // __CXXGRAPH_INPUTOPERATION_IMPL_H__
570+ #endif // __CXXGRAPH_INPUTOPERATION_IMPL_H__
0 commit comments