SAGA API v9.10
Loading...
Searching...
No Matches
grid_memory.cpp
Go to the documentation of this file.
1/**********************************************************
2 * Version $Id$
3 *********************************************************/
4
6// //
7// SAGA //
8// //
9// System for Automated Geoscientific Analyses //
10// //
11// Application Programming Interface //
12// //
13// Library: SAGA_API //
14// //
15//-------------------------------------------------------//
16// //
17// grid_memory.cpp //
18// //
19// Copyright (C) 2005 by Olaf Conrad //
20// //
21//-------------------------------------------------------//
22// //
23// This file is part of 'SAGA - System for Automated //
24// Geoscientific Analyses'. //
25// //
26// This library is free software; you can redistribute //
27// it and/or modify it under the terms of the GNU Lesser //
28// General Public License as published by the Free //
29// Software Foundation, either version 2.1 of the //
30// License, or (at your option) any later version. //
31// //
32// This library is distributed in the hope that it will //
33// be useful, but WITHOUT ANY WARRANTY; without even the //
34// implied warranty of MERCHANTABILITY or FITNESS FOR A //
35// PARTICULAR PURPOSE. See the GNU Lesser General Public //
36// License for more details. //
37// //
38// You should have received a copy of the GNU Lesser //
39// General Public License along with this program; if //
40// not, see <http://www.gnu.org/licenses/>. //
41// //
42//-------------------------------------------------------//
43// //
44// contact: Olaf Conrad //
45// Institute of Geography //
46// University of Goettingen //
47// Goldschmidtstr. 5 //
48// 37077 Goettingen //
49// Germany //
50// //
51// e-mail: oconrad@saga-gis.org //
52// //
54
55//---------------------------------------------------------
56
57
59// //
60// //
61// //
63
64//---------------------------------------------------------
65#include <memory.h>
66
67#include "grid.h"
68#include "parameters.h"
69
70
72// //
73// Caching Options //
74// //
76
77//---------------------------------------------------------
79
80//---------------------------------------------------------
85
86//---------------------------------------------------------
88{
89 if( SG_Dir_Exists(Directory) )
90 {
91 gSG_Grid_Cache_Directory = Directory;
92 }
93}
94
95
97// //
99
100//---------------------------------------------------------
101static int gSG_Grid_Cache_Mode = 0;
102
103//---------------------------------------------------------
105{
106 gSG_Grid_Cache_Mode = Mode;
107}
108
109//---------------------------------------------------------
111{
112 return( gSG_Grid_Cache_Mode );
113}
114
115
117// //
119
120//---------------------------------------------------------
122
123//---------------------------------------------------------
125{
126 if( nBytes >= 0 )
127 {
129 }
130}
131
132//---------------------------------------------------------
133void SG_Grid_Cache_Set_Threshold_MB(double nMegabytes)
134{
136}
137
138//---------------------------------------------------------
143
144//---------------------------------------------------------
146{
147 return( (double)gSG_Grid_Cache_Threshold / (double)N_MEGABYTE_BYTES );
148}
149
150
152// //
153// Memory //
154// //
156
157//---------------------------------------------------------
158bool CSG_Grid::_Memory_Create(bool bCached)
159{
160 if( !m_System.is_Valid() || m_Type == SG_DATATYPE_Undefined )
161 {
162 return( false );
163 }
164
165 _Memory_Destroy();
166
167 if( bCached || _Cache_Check() )
168 {
169 return( _Cache_Create() );
170 }
171
172 return( _Array_Create() );
173}
174
175//---------------------------------------------------------
176void CSG_Grid::_Memory_Destroy(void)
177{
178 SG_FREE_SAFE(m_Index);
179
180 if( is_Cached() )
181 {
182 _Cache_Destroy(false);
183 }
184
185 _Array_Destroy();
186}
187
188
190// //
191// Array //
192// //
194
195//---------------------------------------------------------
196bool CSG_Grid::_Array_Create(void)
197{
198 if( m_System.is_Valid() && m_Type != SG_DATATYPE_Undefined )
199 {
200 _Array_Destroy();
201
202 if( (m_Values = (void **)SG_Malloc(Get_NY() * sizeof(void *))) != NULL )
203 {
204 if( (m_Values[0] = (void *)SG_Calloc(Get_NY(), Get_nLineBytes())) != NULL )
205 {
206 char *pLine = (char *)m_Values[0];
207
208 for(int y=0; y<Get_NY(); y++, pLine+=Get_nLineBytes())
209 {
210 m_Values[y] = pLine;
211 }
212
213 return( true );
214 }
215
216 SG_Free(m_Values);
217
218 m_Values = NULL;
219 }
220
221 SG_UI_Msg_Add_Error(CSG_String::Format("%s: %s [%.2fmb]", _TL("grid"), _TL("memory allocation failed"), (double)Get_NY() * Get_nLineBytes() / N_MEGABYTE_BYTES));
222 }
223
224 return( false );
225}
226
227//---------------------------------------------------------
228void CSG_Grid::_Array_Destroy(void)
229{
230 if( m_Values )
231 {
232 SG_Free(m_Values[0]);
233 SG_Free(m_Values);
234
235 m_Values = NULL;
236 }
237}
238
239
241// //
242// Cache //
243// //
245
246//---------------------------------------------------------
247#define CACHE_FILE_POS(x, y) (m_Cache_Offset + (m_Cache_bFlip ? Get_NY() - 1 - y : y) * m_nBytes_Line + x * m_nBytes_Value)
248
249//---------------------------------------------------------
250#if defined(_SAGA_LINUX)
251#define CACHE_FILE_SEEK fseek
252#else
253#define CACHE_FILE_SEEK _fseeki64
254#endif
255
256//---------------------------------------------------------
258{
259 if( bOn )
260 {
261 return( is_Cached()
262 || _Cache_Create(m_Cache_File , m_Type, m_Cache_Offset, m_Cache_bSwap, m_Cache_bFlip)
263 || _Cache_Create(SG_File_Make_Path("", Get_File_Name(), "dat"), m_Type, m_Cache_Offset, m_Cache_bSwap, m_Cache_bFlip)
264 || _Cache_Create(SG_File_Make_Path("", Get_File_Name(), "sdat"), m_Type, m_Cache_Offset, m_Cache_bSwap, m_Cache_bFlip)
265 || _Cache_Create()
266 );
267 }
268
269 return( !is_Cached() || _Cache_Destroy(true) );
270}
271
272
274// //
276
277//---------------------------------------------------------
278bool CSG_Grid::_Cache_Check(void)
279{
280 sLong nBytes = m_System.Get_NCells() * Get_nValueBytes();
281
283 {
284 if( SG_Grid_Cache_Get_Mode() == 2 ) // confirm
285 {
286 CSG_String s;
287
288 s.Printf("%s\n%s\n%s: %.2fMB",
289 _TL("Shall I activate file caching for new grid."),
290 m_System.Get_Name(),
291 _TL("Total memory size"),
292 (double)nBytes / (double)N_MEGABYTE_BYTES
293 );
294
295 return( SG_UI_Dlg_Continue(s, _TL("Activate Grid File Cache?")) );
296 }
297
298 return( true );
299 }
300
301 return( false );
302}
303
304
306// //
308
309//---------------------------------------------------------
310bool CSG_Grid::_Cache_Create(const CSG_String &File, TSG_Data_Type Data_Type, sLong Offset, bool bSwap, bool bFlip) // open existing file for caching
311{
312 if( !m_System.is_Valid() || m_Type != Data_Type || !SG_File_Exists(File) )
313 {
314 return( false );
315 }
316
317 if( (m_Cache_Stream = fopen(File, "r+b")) == NULL // read and write
318 && (m_Cache_Stream = fopen(File, "rb" )) == NULL ) // read only
319 {
320 return( false );
321 }
322
323 m_Cache_File = File;
324 m_Cache_bTemp = false;
325 m_Cache_Offset = Offset;
326 m_Cache_bSwap = m_Type == SG_DATATYPE_Bit ? false : bSwap;
327 m_Cache_bFlip = bFlip;
328
329 _Array_Destroy();
330
331 return( true );
332}
333
334//---------------------------------------------------------
335bool CSG_Grid::_Cache_Create(void) // create temporary cache file
336{
337 if( !m_System.is_Valid() || (m_Type == SG_DATATYPE_Undefined && is_Cached()) )
338 {
339 return( false );
340 }
341
342 CSG_String File = SG_File_Get_Name_Temp("sg_grd", SG_Grid_Cache_Get_Directory());
343
344 if( (m_Cache_Stream = fopen(File, "w+b")) == NULL ) // read and write, create empty
345 {
346 return( false );
347 }
348
349 m_Cache_File = File;
350 m_Cache_bTemp = true;
351 m_Cache_Offset = 0;
352 m_Cache_bSwap = false;
353 m_Cache_bFlip = false;
354
355 CSG_Array Values(1, m_Values ? 0 : Get_nLineBytes()); // dummy
356
357 for(int y=0; y<Get_NY() && SG_UI_Process_Set_Progress(y, Get_NY()); y++)
358 {
359 fwrite(m_Values ? m_Values[y] : Values.Get_Array(), 1, Get_nLineBytes(), m_Cache_Stream);
360 }
361
363
364 _Array_Destroy();
365
366 return( true );
367}
368
369//---------------------------------------------------------
370bool CSG_Grid::_Cache_Destroy(bool bMemory_Restore)
371{
372 if( is_Cached() )
373 {
374 if( bMemory_Restore && _Array_Create() && !CACHE_FILE_SEEK(m_Cache_Stream, m_Cache_Offset, SEEK_SET) )
375 {
376 for(int y=0; y<Get_NY() && SG_UI_Process_Set_Progress(y, Get_NY()); y++)
377 {
378 fread(m_Values[m_Cache_bFlip ? Get_NY() - 1 - y : y], 1, Get_nLineBytes(), m_Cache_Stream);
379
380 if( m_Cache_bSwap )
381 {
382 char *pValue = (char *)m_Values[y];
383
384 for(int x=0; x<Get_NX(); x++, pValue+=Get_nValueBytes())
385 {
386 _Swap_Bytes(pValue, Get_nValueBytes());
387 }
388 }
389 }
390
392 }
393
394 //-------------------------------------------------
395 fclose(m_Cache_Stream);
396
397 m_Cache_Stream = NULL;
398
399 if( m_Cache_bTemp )
400 {
401 SG_File_Delete(m_Cache_File);
402 }
403
404 return( true );
405 }
406
407 return( false );
408}
409
410
412// //
414
415//---------------------------------------------------------
416void CSG_Grid::_Cache_Set_Value(int x, int y, double Value)
417{
418 char Buffer[8];
419
420 switch( m_Type )
421 {
422 case SG_DATATYPE_Float : (*(float *)Buffer) = (float )(Value); break;
423 case SG_DATATYPE_Double: (*(double *)Buffer) = (double )(Value); break;
424 case SG_DATATYPE_Byte : (*(BYTE *)Buffer) = SG_ROUND_TO_BYTE (Value); break;
425 case SG_DATATYPE_Char : (*(char *)Buffer) = SG_ROUND_TO_CHAR (Value); break;
426 case SG_DATATYPE_Word : (*(WORD *)Buffer) = SG_ROUND_TO_WORD (Value); break;
427 case SG_DATATYPE_Short : (*(short *)Buffer) = SG_ROUND_TO_SHORT(Value); break;
428 case SG_DATATYPE_DWord : (*(DWORD *)Buffer) = SG_ROUND_TO_DWORD(Value); break;
429 case SG_DATATYPE_Int : (*(int *)Buffer) = SG_ROUND_TO_INT (Value); break;
430 case SG_DATATYPE_Long : (*(sLong *)Buffer) = SG_ROUND_TO_SLONG(Value); break;
431
432 default:
433 return;
434 }
435
436 if( m_Cache_bSwap )
437 {
438 _Swap_Bytes(Buffer, Get_nValueBytes());
439 }
440
441 if( !CACHE_FILE_SEEK(m_Cache_Stream, CACHE_FILE_POS(x, y), SEEK_SET) )
442 {
443 fwrite(Buffer, 1, Get_nValueBytes(), m_Cache_Stream);
444 }
445}
446
447//---------------------------------------------------------
448double CSG_Grid::_Cache_Get_Value(int x, int y) const
449{
450 if( !CACHE_FILE_SEEK(m_Cache_Stream, CACHE_FILE_POS(x, y), SEEK_SET) )
451 {
452 char Buffer[8];
453
454 if( fread(Buffer, 1, Get_nValueBytes(), m_Cache_Stream) == (size_t)Get_nValueBytes() )
455 {
456 switch( m_Type )
457 {
458 case SG_DATATYPE_Byte : return( (double)(*(BYTE *)Buffer) );
459 case SG_DATATYPE_Char : return( (double)(*(char *)Buffer) );
460 case SG_DATATYPE_Word : return( (double)(*(WORD *)Buffer) );
461 case SG_DATATYPE_Short : return( (double)(*(short *)Buffer) );
462 case SG_DATATYPE_DWord : return( (double)(*(DWORD *)Buffer) );
463 case SG_DATATYPE_Int : return( (double)(*(int *)Buffer) );
464 case SG_DATATYPE_Long : return( (double)(*(sLong *)Buffer) );
465 case SG_DATATYPE_Float : return( (double)(*(float *)Buffer) );
466 case SG_DATATYPE_Double: return( (double)(*(double *)Buffer) );
467
468 default:
469 break;
470 }
471
472 if( m_Cache_bSwap )
473 {
474 _Swap_Bytes(Buffer, Get_nValueBytes());
475 }
476 }
477 }
478
479 return( 0.0 );
480}
481
482
484// //
485// //
486// //
488
489//---------------------------------------------------------
void SG_UI_Msg_Add_Error(const char *Message)
bool SG_UI_Process_Set_Ready(void)
bool SG_UI_Process_Set_Progress(int Position, int Range)
bool SG_UI_Dlg_Continue(const CSG_String &Message, const CSG_String &Caption)
SAGA_API_DLL_EXPORT bool SG_File_Exists(const CSG_String &FileName)
SAGA_API_DLL_EXPORT void * SG_Malloc(size_t size)
signed long long sLong
Definition api_core.h:158
SAGA_API_DLL_EXPORT void SG_Free(void *memblock)
SAGA_API_DLL_EXPORT CSG_String SG_File_Make_Path(const CSG_String &Directory, const CSG_String &Name)
SAGA_API_DLL_EXPORT bool SG_File_Delete(const CSG_String &FileName)
SAGA_API_DLL_EXPORT void * SG_Calloc(size_t num, size_t size)
SAGA_API_DLL_EXPORT bool SG_Dir_Exists(const CSG_String &Directory)
Definition api_file.cpp:966
SAGA_API_DLL_EXPORT CSG_String SG_File_Get_Name_Temp(const CSG_String &Prefix)
#define SG_FREE_SAFE(PTR)
Definition api_core.h:205
TSG_Data_Type
Definition api_core.h:997
@ SG_DATATYPE_Long
Definition api_core.h:1006
@ SG_DATATYPE_Byte
Definition api_core.h:999
@ SG_DATATYPE_Bit
Definition api_core.h:998
@ SG_DATATYPE_Short
Definition api_core.h:1002
@ SG_DATATYPE_Word
Definition api_core.h:1001
@ SG_DATATYPE_Float
Definition api_core.h:1007
@ SG_DATATYPE_Undefined
Definition api_core.h:1013
@ SG_DATATYPE_Double
Definition api_core.h:1008
@ SG_DATATYPE_Int
Definition api_core.h:1004
@ SG_DATATYPE_Char
Definition api_core.h:1000
@ SG_DATATYPE_DWord
Definition api_core.h:1003
#define SG_Char
Definition api_core.h:536
#define _TL(s)
Definition api_core.h:1568
const SG_Char * Get_File_Name(bool bNative=true) const
const SG_Char * Get_Name(bool bShort=true)
sLong Get_NCells(void) const
Definition grid.h:260
int Get_NY(void) const
Definition grid.h:564
bool Set_Cache(bool bOn)
bool is_Cached(void) const
Definition grid.h:633
int Get_nValueBytes(void) const
Definition grid.h:549
int Get_nLineBytes(void) const
Definition grid.h:550
int Get_NX(void) const
Definition grid.h:563
static CSG_String Format(const char *Format,...)
int Printf(const char *Format,...)
SAGA_API_DLL_EXPORT sLong SG_Grid_Cache_Get_Threshold(void)
SAGA_API_DLL_EXPORT int SG_Grid_Cache_Get_Mode(void)
SAGA_API_DLL_EXPORT const SG_Char * SG_Grid_Cache_Get_Directory(void)
static int gSG_Grid_Cache_Mode
const SG_Char * SG_Grid_Cache_Get_Directory(void)
void SG_Grid_Cache_Set_Threshold(int nBytes)
#define CACHE_FILE_SEEK
int SG_Grid_Cache_Get_Mode(void)
void SG_Grid_Cache_Set_Threshold_MB(double nMegabytes)
static CSG_String gSG_Grid_Cache_Directory
sLong SG_Grid_Cache_Get_Threshold(void)
double SG_Grid_Cache_Get_Threshold_MB(void)
#define CACHE_FILE_POS(x, y)
static sLong gSG_Grid_Cache_Threshold
void SG_Grid_Cache_Set_Mode(int Mode)
void SG_Grid_Cache_Set_Directory(const SG_Char *Directory)
#define SG_ROUND_TO_INT(x)
Definition mat_tools.h:155
#define SG_ROUND_TO_CHAR(x)
Definition mat_tools.h:151
#define SG_ROUND_TO_BYTE(x)
Definition mat_tools.h:150
#define SG_ROUND_TO_SLONG(x)
Definition mat_tools.h:158
#define SG_ROUND_TO_WORD(x)
Definition mat_tools.h:152
#define N_MEGABYTE_BYTES
Definition mat_tools.h:115
#define SG_ROUND_TO_SHORT(x)
Definition mat_tools.h:153
#define SG_ROUND_TO_DWORD(x)
Definition mat_tools.h:154