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