Octopus
detect_format.hpp
Go to the documentation of this file.
1#ifndef PSEUDO_DETECT_FORMAT_HPP
2#define PSEUDO_DETECT_FORMAT_HPP
3
4/*
5 Copyright (C) 2018 Xavier Andrade
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20*/
21
22#include "base.hpp"
23#include <fstream>
24#include <iostream>
25#include <rapidxml.hpp>
26#include <string>
27#include <sys/stat.h>
28#include <sys/types.h>
29#include <unistd.h>
30#include <vector>
31
32namespace pseudopotential {
33
34static pseudopotential::format detect_format(const std::string &filename) {
35
36 // check that the file is not a directory
37 struct stat file_stat;
38 if (stat(filename.c_str(), &file_stat) == -1)
39 return pseudopotential::format::FILE_NOT_FOUND;
40 if (S_ISDIR(file_stat.st_mode))
41 return pseudopotential::format::FILE_NOT_FOUND;
42
43 // now open the file
44 std::ifstream file(filename.c_str());
45
46 if (!file)
47 return pseudopotential::format::FILE_NOT_FOUND;
48
49 // First, try to read the file extension from the filename. This will detect non-xml files
50 std::string extension = filename.substr(filename.find_last_of(".") + 1);
51 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
52
53 if (extension == "psp8" || extension == "drh")
54 return pseudopotential::format::PSP8;
55 if (extension == "psf")
56 return pseudopotential::format::PSF;
57 if (extension == "cpi")
58 return pseudopotential::format::CPI;
59 if (extension == "fhi")
60 return pseudopotential::format::FHI;
61 if (extension == "hgh")
62 return pseudopotential::format::HGH;
63
64 // If the file extension is not recognized, try to parse parse it as XML
65 std::vector<char> buffer((std::istreambuf_iterator<char>(file)),
66 std::istreambuf_iterator<char>());
67 buffer.push_back('\0');
68
69 rapidxml::xml_document<> doc;
70 try {
71 doc.parse<0>(&buffer[0]);
72 // Return the specific format if the file is recognized
73 if (doc.first_node("fpmd:species"))
74 return pseudopotential::format::QSO;
75 if (doc.first_node("qbox:species"))
76 return pseudopotential::format::QSO;
77 if (doc.first_node("PP_INFO"))
78 return pseudopotential::format::UPF1;
79 if (doc.first_node("UPF"))
80 return pseudopotential::format::UPF2;
81 if (doc.first_node("psml"))
82 return pseudopotential::format::PSML;
83 } catch (rapidxml::parse_error xml_error) {
84 // Currently Octopus is passing a folder name to the ps_init() routine, which calls this function.
85 // Here, we loop over all files in that folder, and try to detect their type.
86 // As these folders also contain files, such as Makefile, etc. the catch condition will always be
87 // met, and Octopus would print the confusing error messages. Therefore, the error messages are
88 // disabled, until the whole mechanism is better understood.
89
90 // std::cerr << "Error parsing pseudopotential file, " << filename.c_str() << ", as XML." << std::endl;
91 // std::cerr << "rapidxml error:" << xml_error.what() << std::endl;
92 }
93
94 return pseudopotential::format::UNKNOWN;
95}
96
97} // namespace pseudopotential
98
99#endif
if write to the Free Software Franklin Fifth USA !If the compiler accepts long Fortran it is better to use that and build all the preprocessor definitions in one line In !this the debuggers will provide the right line numbers !If the compiler accepts line number then CARDINAL and ACARDINAL !will put them just a new line or a ampersand plus a new line !These macros should be used in macros that span several lines They should by !put immedialty before a line where a compilation error might occur and at the !end of the macro !Note that the cardinal and newline words are substituted by the program !preprocess pl by the ampersand and by a real new line just before compilation !The assertions are ignored if the code is compiled in not debug when !prints out the assertion the file
Definition: global.h:46
if write to the Free Software Franklin Fifth USA !If the compiler accepts long Fortran it is better to use that and build all the preprocessor definitions in one line In !this the debuggers will provide the right line numbers !If the compiler accepts line number then CARDINAL and ACARDINAL !will put them just a new line or a ampersand plus a new line !These macros should be used in macros that span several lines They should by !put immedialty before a line where a compilation error might occur and at the !end of the macro !Note that the cardinal and newline words are substituted by the program !preprocess pl by the ampersand and by a real new line just before compilation !The assertions are ignored if the code is compiled in not debug when !prints out the assertion string
Definition: global.h:46
int stat(const char *__restrict __file, struct stat *__restrict __buf) __attribute__((__nothrow__