1 // Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
2 
3 #ifndef SPECTMORPH_UTIL_HH
4 #define SPECTMORPH_UTIL_HH
5 
6 #include <string>
7 #include <vector>
8 
9 // operating system: one of these three
10 #if WIN32
11   #define SM_OS_WINDOWS
12 #elif __APPLE__
13   #define SM_OS_MACOS
14 #elif __linux__
15   #define SM_OS_LINUX
16 #elif __FreeBSD__
17   #define SM_OS_LINUX
18 #elif __DragonFly__
19   #define SM_OS_LINUX
20 #else
21   #error "unsupported platform"
22 #endif
23 
24 // detect compiler
25 #if __clang__
26   #define SM_COMP_CLANG
27 #elif __GNUC__ > 2
28   #define SM_COMP_GCC
29 #else
30   #error "unsupported compiler"
31 #endif
32 
33 namespace SpectMorph
34 {
35 
36 /* integer types */
37 typedef uint8_t       uint8;
38 typedef uint32_t      uint32;
39 typedef int64_t       int64;
40 typedef uint64_t      uint64;
41 typedef unsigned int  uint;
42 
43 #define SPECTMORPH_CLASS_NON_COPYABLE(Class)        private: Class (const Class&); Class& operator= (const Class&);
44 
45 #ifdef SM_COMP_GCC
46   #define SPECTMORPH_PRINTF(format_idx, arg_idx)      __attribute__ ((__format__ (gnu_printf, format_idx, arg_idx)))
47 #else
48   #define SPECTMORPH_PRINTF(format_idx, arg_idx)      __attribute__ ((__format__ (__printf__, format_idx, arg_idx)))
49 #endif
50 
51 std::string string_printf (const char *format, ...) SPECTMORPH_PRINTF (1, 2);
52 std::string string_vprintf (const char *format, va_list vargs);
53 
54 std::string string_locale_printf (const char *format, ...) SPECTMORPH_PRINTF (1, 2);
55 
56 void        sm_printf (const char *format, ...) SPECTMORPH_PRINTF (1, 2);
57 
58 enum InstallDir
59 {
60   INSTALL_DIR_BIN,
61   INSTALL_DIR_TEMPLATES,
62   INSTALL_DIR_INSTRUMENTS,
63   INSTALL_DIR_FONTS
64 };
65 
66 std::string sm_get_install_dir (InstallDir p);
67 
68 // data directory is relocatable
69 void        sm_set_pkg_data_dir (const std::string& data_dir);
70 
71 enum UserDir
72 {
73   USER_DIR_INSTRUMENTS,
74   USER_DIR_CACHE, /* FIXME: unify with sm_get_cache_dir */
75   USER_DIR_DATA
76 };
77 
78 std::string sm_get_user_dir (UserDir p);
79 std::string sm_get_default_plan();
80 std::string sm_get_cache_dir();
81 
82 #ifdef SM_OS_MACOS
83 std::string sm_mac_documents_dir();
84 std::string sm_mac_application_support_dir();
85 #endif
86 
87 enum DocumentsDir
88 {
89   DOCUMENTS_DIR_INSTRUMENTS
90 };
91 
92 std::string sm_get_documents_dir (DocumentsDir p);
93 
94 class Error
95 {
96 public:
97   enum class Code {
98     NONE,
99     FILE_NOT_FOUND,
100     FORMAT_INVALID,
101     PARSE_ERROR,
102     STR
103   };
104 
105   Error (Code code) :
106     m_code (code)
107   {
108     switch (code)
109       {
110         case Code::NONE:
111           m_message = "OK";
112           break;
113 
114         case Code::FILE_NOT_FOUND:
115           m_message = "No such file, device or directory";
116           break;
117 
118         case Code::FORMAT_INVALID:
119           m_message = "Invalid format";
120           break;
121 
122         case Code::PARSE_ERROR:
123           m_message = "Parsing error";
124           break;
125 
126         default:
127           m_message = "Unknown error";
128       }
129   }
130   explicit
131   Error (const std::string& message) :
132     m_code (Code::STR),
133     m_message (message)
134   {
135   }
136 
137   Code
138   code()
139   {
140     return m_code;
141   }
142   const char *
143   message()
144   {
145     return m_message.c_str();
146   }
147   operator bool()
148   {
149     return m_code != Code::NONE;
150   }
151 private:
152   Code        m_code;
153   std::string m_message;
154 };
155 
156 #ifdef SM_OS_WINDOWS
157 std::string sm_resolve_link (const std::string& link_file);
158 #endif
159 
160 std::string sha1_hash (const unsigned char *data, size_t len);
161 std::string sha1_hash (const std::string& str);
162 
163 double get_time();
164 
165 std::string to_utf8 (const std::u32string& str);
166 std::u32string to_utf32 (const std::string& utf8);
167 
168 Error read_dir (const std::string& dirname, std::vector<std::string>& files);
169 bool file_exists (const std::string& filename);
170 bool dir_exists (const std::string& dirname);
171 
172 } // namespace SpectMorph
173 
174 /* we want to be able to use sm_debug without extra includes */
175 #include "smdebug.hh"
176 
177 #endif
178