source: main/trunk/greenstone2/build-src/packages/isis-gdl/Fdt.cpp@ 26670

Last change on this file since 26670 was 26668, checked in by davidb, 11 years ago

Code changed from using WIN32 use to _MSC_VER (the difference being the former is set for any Windows based compiler, whilst the latter is specifically set by a MicroSoft Visual Studio compiler). Up to this point the difference was not important, however to allow for cross-compilation (using mingw under Linux to produce native Windows binaries) the difference is imporant, and needs to be used more carefully

  • Property svn:keywords set to Author Date Id Revision
File size: 11.8 KB
Line 
1/**********************************************************************
2 *
3 * Fdt.cpp
4 * Copyright (C) 2003 UNESCO
5 *
6 * A component of the Greenstone digital library software
7 * from the New Zealand Digital Library Project at the
8 * University of Waikato, New Zealand.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 *********************************************************************/
25
26///////////////////////////////////////////////////////////////////////////
27// fdt.cpp
28
29#include "stdafx.h"
30#include "Fdt.h"
31#include <iostream>
32#include <iomanip>
33#include <fstream>
34#include <sstream>
35#include <stdio.h>
36
37//////////////////////////////
38
39CFdt::CFdt()
40// Constructor
41{
42 InitData();
43 InitFields();
44}
45
46//////////////////////////////
47
48CFdt::~CFdt()
49{
50 for (int i = 0; i < m_nFieldCount; i++)
51 {
52#ifndef _MSC_VER
53 CFieldDef* p = (CFieldDef*) m_fieldArray[i];
54#else
55 CFieldDef* p = (CFieldDef*) m_fieldArray.at(i);
56#endif
57 delete p;
58 }
59 m_fieldArray.clear();
60
61 Close();
62}
63
64////////////////////////////
65
66bool CFdt::Open(const _TCHAR *szFileName, bool readOnly)
67{
68 if (!m_bIsEmpty)
69 Close();
70 m_sFileName = szFileName;
71 if (!Load(szFileName))
72 {
73 Close();
74 return false;
75 }
76
77 m_bReadOnly = readOnly;
78 return Seek(0); //
79}
80
81
82
83
84//////////////////////////////
85
86void CFdt::InitData()
87{
88 m_iCurrentRecord = -1;
89 m_sFileName.erase();
90
91 m_bReadOnly = false;
92 m_bIsEmpty = true;
93 m_fdtEntry.Clear();
94 m_bDirty = false;
95 m_aFdt.clear();
96 m_asPrelude.clear();
97 // Suppose the fdt is empty and we are
98 // going to append
99 m_bAppend = true;
100}
101
102//////////////////////////////
103
104void CFdt::Close()
105{
106 if (!m_bIsEmpty)
107 DeleteContents();
108
109 InitData(); // Reset data members
110 m_bIsEmpty = true;
111}
112
113////////////////////////////////////
114
115void CFdt::DeleteContents()
116// Delete the fdt data structures
117{
118 m_aFdt.clear();
119
120}
121
122
123
124bool CFdt::Load(const _TCHAR *dbaseName)
125{
126 std::ifstream in((const char*)dbaseName);
127 if (!in)
128 {
129//#ifdef _WIN32
130// CString strMsg;
131// strMsg.Format(_T("Error opening %s for reading. "), dbaseName);
132// AfxMessageBox(strMsg, MB_OK | MB_ICONEXCLAMATION);
133//#else
134 std::cout << _T("Error opening") << dbaseName << _T("for reading") << std::endl;
135//#endif
136 return false;
137 }
138
139
140 std::string s;
141
142 while (std::getline(in,s) && s.substr(0,3) != "***")
143 {
144 m_asPrelude.push_back(s);
145 }
146
147 while (std::getline(in,s))
148 {
149 CFdtEntry e;
150 strncpy(e.name, s.c_str(), FDT_NAME_LENG);
151 e.name[FDT_NAME_LENG] = _T('\0');
152 for (int i=FDT_NAME_LENG-1; e.name[i]==_T(' '); e.name[i--]=_T('\0'))
153 ;
154 if (s[FDT_NAME_LENG] == _T(' ')) //no subfield delimiters spec.
155 e.subfields[0] = _T('\0');
156 else
157 {
158 strncpy(e.subfields, s.c_str()+FDT_NAME_LENG, FDT_SFLD_LENG);
159 e.subfields[FDT_SFLD_LENG] = _T('\0');
160 for (int i= FDT_SFLD_LENG-1; e.subfields[i]==_T(' '); e.subfields[i--]='\0')
161 ;
162 }
163 sscanf(s.c_str() + FDT_NAME_LENG + FDT_SFLD_LENG, "%d %d %d %d",
164 &e.tag, &e.len, &e.type, &e.rep);
165 m_aFdt.push_back(e);
166 }
167 in.close();
168 return true;
169}
170
171
172
173
174
175
176// Define the fields used for the dictionary
177
178static CFieldDef fdtFields[7] = {
179 {"Name", 'C', 30, 30, 0, 0, 30},
180 {"Subfields", 'C', 20, 20, 0, 30, 20},
181 {"Tag", 'N', 4, 4, 0,50, 4},
182 {"Len", 'N', 4, 4, 0,54, 4},
183 {"Type", 'N', 1, 1, 0,58, 4},
184 {"Rep", 'C', 1, 1, 0,62, 4},
185 {0, 0, 0, 0, 0, 0, 0}
186};
187
188
189
190
191
192
193//+----------------------------------------------------------------
194//
195// Member: Store(const char* fileName)
196//
197// Synopsis: Store dictionary tables on a file
198//
199// Parameters:
200//
201// fileName -- Full path of dictionary file
202//
203//-----------------------------------------------------------------
204
205void FormatFdtEntry(CFdtEntry &e, ustring &s)
206{
207#ifdef _WIN32
208 // Not sure why we could have code here that only runs if on Windows
209 ustringstream ost;
210
211 ost.setf(std::ios_base::left, std::ios_base::adjustfield);
212 ost << std::setw(30) << e.name << std::setw(20) << e.subfields;
213 ost.setf(std::ios_base::internal,std::ios_base::adjustfield);
214 ost << " " << e.tag << " " << e.len << " " << e.type << " " << e.rep;
215 s = ost.str();
216#endif
217}
218
219void CFdt::Store(const char* fileName)
220{
221 if (m_bDirty)
222 {
223 Flush();
224 m_bDirty = false;
225 }
226
227 std::ofstream out((const char *) fileName);
228 TRACE(_T("\n<CFdt::Store> fileName=%s"),fileName);
229 for (int i=0; i<m_asPrelude.size(); i++)
230 out << m_asPrelude[i] << std::endl;
231
232 out << "***" << std::endl;
233
234 ustring s;
235#ifdef _MSC_VER
236 for (i=0; i< m_aFdt.size(); i++)
237#else
238 for (int i=0; i< m_aFdt.size(); i++)
239#endif
240 {
241 FormatFdtEntry(m_aFdt[i], s);
242 out << s << std::endl;
243 }
244 out.close();
245
246}
247
248//////////////////////////////
249
250int CFdt::InitFields ()
251{
252 m_nFieldCount = 0;
253
254 for (int i = 0; fdtFields[i].width != 0; i++)
255 {
256 CFieldDef* fld = (CFieldDef*) new CFieldDef();
257 //TRACE("\n<CFdt::InitFields>i=%d after new",i);
258 //TRACE("<CFdt::InitFields>After SetAtGrow");
259 strcpy(fld->name, fdtFields[i].name);
260 fld->type = fdtFields[i].type;
261 fld->len = fdtFields[i].len;
262 fld->width = fdtFields[i].width;
263 fld->decimals = fdtFields[i].decimals;
264 fld->offset = fdtFields[i].offset;
265 fld->display_width = fdtFields[i].display_width;
266
267 int l = strlen(fld->name);
268 if (fld->width < l)
269 fld->width = static_cast<short>(l);
270
271 m_fieldArray.push_back(fld);
272 m_nFieldCount++;
273 }
274 //TRACE("\n<CFdt::InitFields>InitField After loop");
275 return 1;
276}
277
278////////////////////////////////////////////////////////////////////
279
280CFieldDef* CFdt::GetField(int n) const
281// Returns field info
282{
283 ASSERT(n >= 0 && n <= m_nFieldCount);
284#ifndef _MSC_VER
285 return (CFieldDef*) m_fieldArray[n];
286#else
287 return (CFieldDef*) m_fieldArray.at(n);
288#endif
289}
290
291/////////////////////////////////////////////////////////////////////
292// Methods for accessing and maintaining the list of CDictTRecords
293// pointers
294
295////////////////////////////
296// First the List Accessors
297////////////////////////////
298
299CFdtEntry CFdt::GetAt(int i)
300{
301#ifndef _MSC_VER
302 return m_aFdt[i];
303#else
304 return m_aFdt.at(i);
305#endif
306
307}
308
309
310//////////////////////////
311
312const CFdtEntry CFdt::GetAt(int i) const
313{
314#ifndef _MSC_VER
315 return m_aFdt[i];
316#else
317 return m_aFdt.at(i);
318#endif
319}
320
321//////////////////////////
322// And now the modifiers
323//////////////////////////
324
325int CFdt::Append(CFdtEntry& e)
326{
327 int n = m_aFdt.size();
328 m_aFdt.push_back(e);
329 m_iCurrentRecord = -1;
330 m_bIsEmpty = false;
331
332 return m_aFdt.size();
333}
334
335
336/**-------------------------------------------------------------------
337 * RemoveAt(int i)
338 *
339 *--------------------------------------------------------------------
340 */
341void CFdt::RemoveAt(int i)
342{
343
344 m_aFdt.erase(m_aFdt.begin()+i);
345 m_iCurrentRecord = -1;
346}
347
348/**-------------------------------------------------------------------
349 * SetAt(int i, CFdtEntry& e)
350 *
351 *--------------------------------------------------------------------
352 */
353void CFdt::SetAt(int i, CFdtEntry& e)
354{
355
356 m_aFdt[i] = e;
357 // Force reloading
358 m_iCurrentRecord = -1;
359}
360
361/////////////////////////////////////////////////////////////////
362//
363// We use a buffer "m_fdtEntry" to hold the content of the current
364// fdt entry. This buffer is filled by the "Seek" member function
365// as follow:
366//
367
368//////////////////////////////
369
370bool CFdt::Seek(long iRecord)
371{
372
373 // move to new record and flush changes of previous record
374 if (iRecord < 0 || iRecord > GetRecordCount())
375 return false;
376 else if (iRecord == m_iCurrentRecord)
377 return true;
378
379 if (m_iCurrentRecord != -1 && m_bDirty)
380 Flush();
381 if (m_bDirty)
382 /*AfxMessageBox(_T("Seek Alert Modification not saved"))*/;
383 m_iCurrentRecord = iRecord;
384
385 if (iRecord == GetRecordCount())
386 {
387 m_fdtEntry.Clear();
388 m_bAppend = true;
389 }
390 else
391 {
392 TRACE(_T("\n<CFdt::Seek> Load iRecord=%d GetRecordCount()=%d"), iRecord, GetRecordCount());
393 m_fdtEntry = GetAt(iRecord);
394 m_bAppend = false;
395 }
396 m_bDirty = false;
397 return true;
398}
399
400
401
402//+------------------------------------------------------------------
403//
404// Member: Flush()
405//
406// Synopsis: Moves the changes made to the current record from
407// the buffer to the dictionary data structure so that
408// they are effective.
409//-------------------------------------------------------------------
410
411void CFdt::Flush()
412{
413 if (m_iCurrentRecord == GetRecordCount())
414 {
415 Append(m_fdtEntry);
416 }
417 else
418 {
419 SetAt(m_iCurrentRecord, m_fdtEntry);
420 }
421 m_bDirty = false;
422}
423
424//////////////////////////////////////////////////////////////
425// Get the value of field n for the current record
426//
427
428bool CFdt::GetValue(int n, std::string& result)
429// Read value from buffer
430{
431 ASSERT(n >= 0 && n <= m_nFieldCount);
432 ASSERT(m_iCurrentRecord >= 0 && m_iCurrentRecord <= GetRecordCount());
433
434 if (!(n >= 0 && n <= m_nFieldCount))
435 return false;
436
437 result.erase();
438
439 std::ostringstream os;
440 switch (n)
441 {
442 case 0: // Field Name
443 os << m_fdtEntry.name;
444 result = os.str();
445 break;
446 case 1: // Subfields
447 os << m_fdtEntry.subfields;
448 result = os.str();
449 break;
450 case 2: // Tag
451 if (m_fdtEntry.tag == 0)
452 result = "";
453 else
454 {
455 os << m_fdtEntry.tag;
456 result = os.str();
457 }
458 break;
459 case 3: // length
460 if (m_fdtEntry.len == 0)
461 result = "";
462 else
463 {
464 os << m_fdtEntry.len;
465 result = os.str();
466 }
467 break;
468 case 4: // type
469 if (m_fdtEntry.type == 0)
470 result = "";
471 else
472 {
473 os << m_fdtEntry.type;
474 result = os.str();
475 }
476 break;
477 case 5: // Rep
478 if (m_fdtEntry.rep == 0)
479 result = "";
480 else
481 {
482 os << m_fdtEntry.rep;
483 result = os.str();
484 }
485 break;
486 }
487 return true;
488}
489
490
491//////////////////////////////
492
493bool CFdt::SetValue(int n, const char* pszValue)
494// Write value to buffer
495{
496 ASSERT(n >= 0 && n <= m_nFieldCount);
497 ASSERT(m_iCurrentRecord >= 0 && m_iCurrentRecord <= GetRecordCount());
498
499 if (m_bReadOnly)
500 return false;
501
502 if (!(n >= 0 && n <= m_nFieldCount))
503 return false;
504
505 bool bEmpty = true;
506
507
508 switch (n)
509 {
510 case 0: // Name
511 strcpy(m_fdtEntry.name,(const char*)pszValue);
512 // TRACE("\nvalue=%s num=%d",pszValue,m_tRecord.num);
513 break;
514 case 1: // Subfields
515 strcpy(m_fdtEntry.subfields,(const char*)pszValue);
516 // TRACE("\nvalue=%s name=%d",pszValue,m_tRecord.name);
517 break;
518 case 2: // Tag
519 m_fdtEntry.tag = _ttoi(pszValue);
520 // TRACE("\nvalue=%s loc=%d",pszValue,m_tRecord.loc);
521 break;
522 case 3: // Len
523 m_fdtEntry.len = _ttoi(pszValue);
524 // TRACE("\nvalue=%s wid=%d",pszValue,m_tRecord.wid);
525 break;
526 case 4: // Type
527 m_fdtEntry.type = _ttoi(pszValue);
528 break;
529 case 5: // Rep
530 m_fdtEntry.type = _ttoi(pszValue);
531 break;
532 }
533 m_bDirty = true;
534
535 return true;
536}
537
Note: See TracBrowser for help on using the repository browser.