/[svn]/libgig/trunk/src/helper.h
ViewVC logotype

Contents of /libgig/trunk/src/helper.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3185 - (show annotations) (download) (as text)
Wed May 17 15:42:58 2017 UTC (6 years, 10 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 10308 byte(s)
* Serialization: Handle human readable boolean text representations like
  "yes", "no", "true", "false" in Archive::setAutoValue() as expected.
* Bumped version (4.0.0.svn24).

1 /***************************************************************************
2 * *
3 * libgig - C++ cross-platform Gigasampler format file access library *
4 * *
5 * Copyright (C) 2003-2017 by Christian Schoenebeck *
6 * <cuse@users.sourceforge.net> *
7 * *
8 * This library is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This library is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this library; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 ***************************************************************************/
23
24 #ifndef __LIBGIG_HELPER_H__
25 #define __LIBGIG_HELPER_H__
26
27 #include <string.h>
28 #include <string>
29 #include <sstream>
30 #include <algorithm>
31
32 #if defined(WIN32) && !HAVE_CONFIG_H
33 # include "../win32/libgig_private.h" // like config.h, automatically generated by Dev-C++
34 # define PACKAGE "libgig"
35 # define VERSION VER_STRING // VER_STRING defined in libgig_private.h
36 #endif // WIN32
37
38 #include "RIFF.h"
39
40 // *************** Helper Functions **************
41 // *
42
43 template<class T> inline std::string ToString(T o) {
44 std::stringstream ss;
45 ss << o;
46 return ss.str();
47 }
48
49 inline std::string toLowerCase(std::string s) {
50 std::transform(s.begin(), s.end(), s.begin(), ::tolower);
51 return s;
52 }
53
54 inline long Min(long A, long B) {
55 return (A > B) ? B : A;
56 }
57
58 inline long Abs(long val) {
59 return (val > 0) ? val : -val;
60 }
61
62 inline void swapBytes_16(void* Word) {
63 uint8_t byteCache = *((uint8_t*) Word);
64 *((uint8_t*) Word) = *((uint8_t*) Word + 1);
65 *((uint8_t*) Word + 1) = byteCache;
66 }
67
68 inline void swapBytes_32(void* Word) {
69 uint8_t byteCache = *((uint8_t*) Word);
70 *((uint8_t*) Word) = *((uint8_t*) Word + 3);
71 *((uint8_t*) Word + 3) = byteCache;
72 byteCache = *((uint8_t*) Word + 1);
73 *((uint8_t*) Word + 1) = *((uint8_t*) Word + 2);
74 *((uint8_t*) Word + 2) = byteCache;
75 }
76
77 inline void swapBytes_64(void* Word) {
78 uint8_t byteCache = ((uint8_t*)Word)[0];
79 ((uint8_t*)Word)[0] = ((uint8_t*)Word)[7];
80 ((uint8_t*)Word)[7] = byteCache;
81 byteCache = ((uint8_t*)Word)[1];
82 ((uint8_t*)Word)[1] = ((uint8_t*)Word)[6];
83 ((uint8_t*)Word)[6] = byteCache;
84 byteCache = ((uint8_t*)Word)[2];
85 ((uint8_t*)Word)[2] = ((uint8_t*)Word)[5];
86 ((uint8_t*)Word)[5] = byteCache;
87 byteCache = ((uint8_t*)Word)[3];
88 ((uint8_t*)Word)[3] = ((uint8_t*)Word)[4];
89 ((uint8_t*)Word)[4] = byteCache;
90 }
91
92 inline void swapBytes(void* Word, uint64_t WordSize) {
93 uint8_t byteCache;
94 uint64_t lo = 0, hi = WordSize - 1;
95 for (; lo < hi; hi--, lo++) {
96 byteCache = *((uint8_t*) Word + lo);
97 *((uint8_t*) Word + lo) = *((uint8_t*) Word + hi);
98 *((uint8_t*) Word + hi) = byteCache;
99 }
100 }
101
102 /**
103 * Stores a 16 bit integer in memory using little-endian format.
104 *
105 * @param pData - memory pointer
106 * @param data - integer to be stored
107 */
108 inline void store16(uint8_t* pData, uint16_t data) {
109 pData[0] = data;
110 pData[1] = data >> 8;
111 }
112
113 /**
114 * Stores a 32 bit integer in memory using little-endian format.
115 *
116 * @param pData - memory pointer
117 * @param data - integer to be stored
118 */
119 inline void store32(uint8_t* pData, uint32_t data) {
120 pData[0] = data;
121 pData[1] = data >> 8;
122 pData[2] = data >> 16;
123 pData[3] = data >> 24;
124 }
125
126 /**
127 * Loads a 32 bit integer in memory using little-endian format.
128 *
129 * @param pData - memory pointer
130 * @returns 32 bit data word
131 */
132 inline uint32_t load32(uint8_t* pData) {
133 return uint32_t(pData[0]) |
134 uint32_t(pData[1]) << 8 |
135 uint32_t(pData[2]) << 16 |
136 uint32_t(pData[3]) << 24;
137 }
138
139 /**
140 * Swaps the order of the data words in the given memory area
141 * with a granularity given by \a WordSize.
142 *
143 * @param pData - pointer to the memory area to be swapped
144 * @param AreaSize - size of the memory area to be swapped (in bytes)
145 * @param WordSize - size of the data words (in bytes)
146 */
147 inline void SwapMemoryArea(void* pData, unsigned long AreaSize, uint WordSize) {
148 if (!AreaSize) return; // AreaSize==0 would cause a segfault here
149 switch (WordSize) { // TODO: unefficient
150 case 1: {
151 uint8_t* pDst = (uint8_t*) pData;
152 uint8_t cache;
153 unsigned long lo = 0, hi = AreaSize - 1;
154 for (; lo < hi; hi--, lo++) {
155 cache = pDst[lo];
156 pDst[lo] = pDst[hi];
157 pDst[hi] = cache;
158 }
159 break;
160 }
161 case 2: {
162 uint16_t* pDst = (uint16_t*) pData;
163 uint16_t cache;
164 unsigned long lo = 0, hi = (AreaSize >> 1) - 1;
165 for (; lo < hi; hi--, lo++) {
166 cache = pDst[lo];
167 pDst[lo] = pDst[hi];
168 pDst[hi] = cache;
169 }
170 break;
171 }
172 case 4: {
173 uint32_t* pDst = (uint32_t*) pData;
174 uint32_t cache;
175 unsigned long lo = 0, hi = (AreaSize >> 2) - 1;
176 for (; lo < hi; hi--, lo++) {
177 cache = pDst[lo];
178 pDst[lo] = pDst[hi];
179 pDst[hi] = cache;
180 }
181 break;
182 }
183 default: {
184 uint8_t* pCache = new uint8_t[WordSize]; // TODO: unefficient
185 unsigned long lo = 0, hi = AreaSize - WordSize;
186 for (; lo < hi; hi -= WordSize, lo += WordSize) {
187 memcpy(pCache, (uint8_t*) pData + lo, WordSize);
188 memcpy((uint8_t*) pData + lo, (uint8_t*) pData + hi, WordSize);
189 memcpy((uint8_t*) pData + hi, pCache, WordSize);
190 }
191 if (pCache) delete[] pCache;
192 break;
193 }
194 }
195 }
196
197 /** @brief Load given info field (string).
198 *
199 * Load info field string from given info chunk (\a ck) and save value to \a s.
200 */
201 inline void LoadString(RIFF::Chunk* ck, std::string& s) {
202 if (ck) {
203 const char* str = (char*)ck->LoadChunkData();
204 int size = (int) ck->GetSize();
205 int len;
206 for (len = 0 ; len < size ; len++)
207 if (str[len] == '\0') break;
208 s.assign(str, len);
209 ck->ReleaseChunkData();
210 }
211 }
212
213 /** @brief Apply given INFO field to the respective chunk.
214 *
215 * Apply given info value string to given info chunk, which is a
216 * subchunk of INFO list chunk \a lstINFO. If the given chunk already
217 * exists, value \a s will be applied. Otherwise if it doesn't exist yet
218 * and either \a s or \a sDefault is not an empty string, such a chunk
219 * will be created and either \a s or \a sDefault will be applied
220 * (depending on which one is not an empty string, if both are not an
221 * empty string \a s will be preferred).
222 *
223 * @param ChunkID - 32 bit RIFF chunk ID of INFO subchunk (only used in case \a ck is NULL)
224 * @param ck - INFO (sub)chunk where string should be stored to
225 * @param lstINFO - parent (INFO) RIFF list chunk
226 * @param s - current value of info field
227 * @param sDefault - default value
228 * @param bUseFixedLengthStrings - should a specific string size be forced in the chunk?
229 * @param size - wanted size of the INFO chunk. This is ignored if bUseFixedLengthStrings is false.
230 */
231 inline void SaveString(uint32_t ChunkID, RIFF::Chunk* ck, RIFF::List* lstINFO, const std::string& s, const std::string& sDefault, bool bUseFixedLengthStrings, int size) {
232 if (ck) { // if chunk exists already, use 's' as value
233 if (!bUseFixedLengthStrings) size = (int) s.size() + 1;
234 ck->Resize(size);
235 char* pData = (char*) ck->LoadChunkData();
236 strncpy(pData, s.c_str(), size);
237 } else if (s != "" || sDefault != "" || bUseFixedLengthStrings) { // create chunk
238 const std::string& sToSave = (s != "") ? s : sDefault;
239 if (!bUseFixedLengthStrings) size = (int) sToSave.size() + 1;
240 ck = lstINFO->AddSubChunk(ChunkID, size);
241 char* pData = (char*) ck->LoadChunkData();
242 strncpy(pData, sToSave.c_str(), size);
243 }
244 }
245
246 // private helper function to convert progress of a subprocess into the global progress
247 inline void __notify_progress(RIFF::progress_t* pProgress, float subprogress) {
248 if (pProgress && pProgress->callback) {
249 const float totalrange = pProgress->__range_max - pProgress->__range_min;
250 const float totalprogress = pProgress->__range_min + subprogress * totalrange;
251 pProgress->factor = totalprogress;
252 pProgress->callback(pProgress); // now actually notify about the progress
253 }
254 }
255
256 // private helper function to divide a progress into subprogresses
257 inline void __divide_progress(RIFF::progress_t* pParentProgress, RIFF::progress_t* pSubProgress, float totalTasks, float currentTask) {
258 if (pParentProgress && pParentProgress->callback) {
259 const float totalrange = pParentProgress->__range_max - pParentProgress->__range_min;
260 pSubProgress->callback = pParentProgress->callback;
261 pSubProgress->custom = pParentProgress->custom;
262 pSubProgress->__range_min = pParentProgress->__range_min + totalrange * currentTask / totalTasks;
263 pSubProgress->__range_max = pSubProgress->__range_min + totalrange / totalTasks;
264 }
265 }
266
267 #endif // __LIBGIG_HELPER_H__

  ViewVC Help
Powered by ViewVC