2 |
* * |
* * |
3 |
* libgig - C++ cross-platform Gigasampler format file access library * |
* libgig - C++ cross-platform Gigasampler format file access library * |
4 |
* * |
* * |
5 |
* Copyright (C) 2003-2019 by Christian Schoenebeck * |
* Copyright (C) 2003-2021 by Christian Schoenebeck * |
6 |
* <cuse@users.sourceforge.net> * |
* <cuse@users.sourceforge.net> * |
7 |
* * |
* * |
8 |
* This library is free software; you can redistribute it and/or modify * |
* This library is free software; you can redistribute it and/or modify * |
28 |
#include <string> |
#include <string> |
29 |
#include <sstream> |
#include <sstream> |
30 |
#include <algorithm> |
#include <algorithm> |
31 |
|
#include <assert.h> |
32 |
|
|
33 |
#if defined(WIN32) && !HAVE_CONFIG_H |
#if defined(WIN32) && !HAVE_CONFIG_H && !defined(_MSC_VER) |
34 |
# include "../win32/libgig_private.h" // like config.h, automatically generated by Dev-C++ |
# include "../win32/libgig_private.h" // like config.h, automatically generated by Dev-C++ |
35 |
# define PACKAGE "libgig" |
# define PACKAGE "libgig" |
36 |
# define VERSION VER_STRING // VER_STRING defined in libgig_private.h |
# define VERSION VER_STRING // VER_STRING defined in libgig_private.h |
37 |
#endif // WIN32 |
#endif // WIN32 |
38 |
|
|
39 |
#if HAVE_CONFIG_H /*&& !HAVE_VASPRINTF*/ && defined(WIN32) |
#if (HAVE_CONFIG_H /*&& !HAVE_VASPRINTF*/ && defined(WIN32)) || defined(_MSC_VER) |
40 |
# include <stdarg.h> |
# include <stdarg.h> |
41 |
int vasprintf(char** ret, const char* format, va_list arg); |
int vasprintf(char** ret, const char* format, va_list arg); |
42 |
#endif |
#endif |
43 |
|
|
44 |
|
#if defined(_MSC_VER) |
45 |
|
# if _MSC_VER < 1900 |
46 |
|
# error versions prior to msvc 2015 have not been tested |
47 |
|
# else |
48 |
|
# include <BaseTsd.h> |
49 |
|
typedef SSIZE_T ssize_t; |
50 |
|
# endif |
51 |
|
#endif |
52 |
|
|
53 |
#include "RIFF.h" |
#include "RIFF.h" |
54 |
|
|
55 |
// *************** Helper Functions ************** |
// *************** Helper Functions ************** |
66 |
va_list args; |
va_list args; |
67 |
va_start(args, fmt); |
va_start(args, fmt); |
68 |
char* buf = NULL; |
char* buf = NULL; |
69 |
vasprintf(&buf, fmt, args); |
const int n = vasprintf(&buf, fmt, args); |
70 |
std::string res = buf; |
assert(n >= 0); |
71 |
|
std::string res = (buf && n > 0) ? buf : ""; |
72 |
if (buf) free(buf); |
if (buf) free(buf); |
73 |
va_end(args); |
va_end(args); |
74 |
return res; |
return res; |
152 |
} |
} |
153 |
|
|
154 |
/** |
/** |
155 |
|
* Stores a 64 bit integer in memory using little-endian format. |
156 |
|
* |
157 |
|
* @param pData - memory pointer |
158 |
|
* @param data - integer to be stored |
159 |
|
*/ |
160 |
|
inline void store64(uint8_t* pData, uint64_t data) { |
161 |
|
pData[0] = data; |
162 |
|
pData[1] = data >> 8; |
163 |
|
pData[2] = data >> 16; |
164 |
|
pData[3] = data >> 24; |
165 |
|
pData[4] = data >> 32; |
166 |
|
pData[5] = data >> 40; |
167 |
|
pData[6] = data >> 48; |
168 |
|
pData[7] = data >> 56; |
169 |
|
} |
170 |
|
|
171 |
|
/** |
172 |
* Loads a 16 bit integer in memory using little-endian format. |
* Loads a 16 bit integer in memory using little-endian format. |
173 |
* |
* |
174 |
* @param pData - memory pointer |
* @param pData - memory pointer |
325 |
} |
} |
326 |
} |
} |
327 |
|
|
328 |
#ifdef _WIN32 |
// private helper function to divide a progress into subprogresses |
329 |
# define NATIVE_PATH_SEPARATOR '\\' |
inline void __divide_progress(RIFF::progress_t* pParentProgress, RIFF::progress_t* pSubProgress, float total, float lo, float hi) { |
330 |
#else |
if (pParentProgress && pParentProgress->callback) { |
331 |
# define NATIVE_PATH_SEPARATOR '/' |
const float totalrange = pParentProgress->__range_max - pParentProgress->__range_min; |
332 |
|
pSubProgress->callback = pParentProgress->callback; |
333 |
|
pSubProgress->custom = pParentProgress->custom; |
334 |
|
pSubProgress->__range_min = pParentProgress->__range_min + totalrange * (lo / total); |
335 |
|
pSubProgress->__range_max = pSubProgress->__range_min + totalrange * ((hi-lo) / total); |
336 |
|
} |
337 |
|
} |
338 |
|
|
339 |
|
|
340 |
|
/***************************************************************************** |
341 |
|
* Any problems with any of the following helper functions? * |
342 |
|
* * |
343 |
|
* Then please first have a look at their current TEST CASES at * |
344 |
|
* src/testcases/HelperTest.cpp as basis for your modifications! * |
345 |
|
*****************************************************************************/ |
346 |
|
|
347 |
|
|
348 |
|
/// Removes one or more consecutive occurences of @a needle from the end of @a haystack. |
349 |
|
inline std::string strip2ndFromEndOf1st(const std::string haystack, char needle) { |
350 |
|
if (haystack.empty()) return haystack; |
351 |
|
if (*haystack.rbegin() != needle) return haystack; |
352 |
|
for (int i = haystack.length() - 1; i >= 0; --i) |
353 |
|
if (haystack[i] != needle) |
354 |
|
return haystack.substr(0, i+1); |
355 |
|
return ""; |
356 |
|
} |
357 |
|
|
358 |
|
#ifndef NATIVE_PATH_SEPARATOR |
359 |
|
# ifdef _WIN32 |
360 |
|
# define NATIVE_PATH_SEPARATOR '\\' |
361 |
|
# else |
362 |
|
# define NATIVE_PATH_SEPARATOR '/' |
363 |
|
# endif |
364 |
#endif |
#endif |
365 |
|
|
366 |
/** |
/** |
368 |
* passing "/some/path" would return "/some". |
* passing "/some/path" would return "/some". |
369 |
*/ |
*/ |
370 |
inline std::string parentPath(const std::string path) { |
inline std::string parentPath(const std::string path) { |
371 |
std::size_t pos = path.find_last_of(NATIVE_PATH_SEPARATOR); |
if (path.empty()) return path; |
372 |
return (pos == std::string::npos) ? path : path.substr(0, pos); |
std::string s = strip2ndFromEndOf1st(path, NATIVE_PATH_SEPARATOR); |
373 |
|
if (s.empty()) { |
374 |
|
s.push_back(NATIVE_PATH_SEPARATOR); // i.e. return "/" |
375 |
|
return s; |
376 |
|
} |
377 |
|
#if defined(_WIN32) |
378 |
|
if (s.length() == 2 && s[1] == ':') |
379 |
|
return s; |
380 |
|
#endif |
381 |
|
std::size_t pos = s.find_last_of(NATIVE_PATH_SEPARATOR); |
382 |
|
if (pos == std::string::npos) return ""; |
383 |
|
if (pos == 0) { |
384 |
|
s = ""; |
385 |
|
s.push_back(NATIVE_PATH_SEPARATOR); // i.e. return "/" |
386 |
|
return s; |
387 |
|
} |
388 |
|
return s.substr(0, pos); |
389 |
} |
} |
390 |
|
|
391 |
/** |
/** |
393 |
* "/some/path" would return "path". |
* "/some/path" would return "path". |
394 |
*/ |
*/ |
395 |
inline std::string lastPathComponent(const std::string path) { |
inline std::string lastPathComponent(const std::string path) { |
396 |
|
#if defined(_WIN32) |
397 |
|
if (path.length() == 2 && path[1] == ':') |
398 |
|
return ""; |
399 |
|
#endif |
400 |
std::size_t pos = path.find_last_of(NATIVE_PATH_SEPARATOR); |
std::size_t pos = path.find_last_of(NATIVE_PATH_SEPARATOR); |
401 |
return (pos == std::string::npos) ? path : path.substr(pos+1); |
return (pos == std::string::npos) ? path : path.substr(pos+1); |
402 |
} |
} |
408 |
inline std::string pathWithoutExtension(const std::string path) { |
inline std::string pathWithoutExtension(const std::string path) { |
409 |
std::size_t posSep = path.find_last_of(NATIVE_PATH_SEPARATOR); |
std::size_t posSep = path.find_last_of(NATIVE_PATH_SEPARATOR); |
410 |
std::size_t posBase = (posSep == std::string::npos) ? 0 : posSep+1; |
std::size_t posBase = (posSep == std::string::npos) ? 0 : posSep+1; |
411 |
std::size_t posDot = path.find_last_of(".", posBase); |
std::size_t posDot = path.find_last_of("."); |
412 |
return (posDot != std::string::npos && posDot > posBase) |
return (posDot != std::string::npos && posDot > posBase) |
413 |
? path.substr(0, posDot) : path; |
? path.substr(0, posDot) : path; |
414 |
} |
} |
420 |
inline std::string extensionOfPath(const std::string path) { |
inline std::string extensionOfPath(const std::string path) { |
421 |
std::size_t posSep = path.find_last_of(NATIVE_PATH_SEPARATOR); |
std::size_t posSep = path.find_last_of(NATIVE_PATH_SEPARATOR); |
422 |
std::size_t posBase = (posSep == std::string::npos) ? 0 : posSep+1; |
std::size_t posBase = (posSep == std::string::npos) ? 0 : posSep+1; |
423 |
std::size_t posDot = path.find_last_of(".", posBase); |
std::size_t posDot = path.find_last_of("."); |
424 |
return (posDot != std::string::npos && posDot > posBase) |
return (posDot != std::string::npos && posDot > posBase) |
425 |
? path.substr(posDot+1) : ""; |
? path.substr(posDot+1) : ""; |
426 |
} |
} |
436 |
: path1 + path2; |
: path1 + path2; |
437 |
} |
} |
438 |
|
|
439 |
|
/** |
440 |
|
* Returns a hex string representation of the binary data being passed. |
441 |
|
*/ |
442 |
|
inline std::string binToHexStr(const void* pData, size_t sz) { |
443 |
|
std::string s; |
444 |
|
for (size_t i = 0; i < sz; ++i) { |
445 |
|
s += strPrint("%02x", ((const char*)pData)[i]); |
446 |
|
} |
447 |
|
return s; |
448 |
|
} |
449 |
|
|
450 |
#endif // __LIBGIG_HELPER_H__ |
#endif // __LIBGIG_HELPER_H__ |