source: main/trunk/greenstone2/build-src/packages/isis-gdl/Master.h@ 26670

Last change on this file since 26670 was 6127, checked in by mdewsnip, 20 years ago

IsisGdl package for reading CDS/ISIS databases. Provided by Jean-Claude Dauphin at UNESCO, and modified slightly to compile and run under Linux.

  • Property svn:keywords set to Author Date Id Revision
File size: 15.7 KB
Line 
1/**********************************************************************
2 *
3 * Master.h
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// Master.h: Master File Record object
28/////////////////////////////////////// */
29
30#ifndef __MASTER_RECORD_H__
31#define __MASTER_RECORD_H__
32
33#include "BlkFile.h"
34#include <vector>
35#include <map>
36#include <sstream>
37
38
39
40// Length in bytes of master file header
41#define MFCTLLEN sizeof(SMfHeader)+sizeof(SMfHeader) // Length in bytes of master file header
42
43const int MFALIGN = 2; // Master file record alignment
44const int MFBLKSIZE = 512; // Master file block size
45
46typedef short int ISIS_INT;
47typedef long int ISIS_LONG;
48
49#ifdef UNIX_BIREME
50 //Length of Leader in master record
51 inline int GetLeaderSize()
52 {
53 return (2*sizeof(ISIS_LONG)+6*sizeof(ISIS_INT));
54 }
55 // Mini Leader length guaranteed to be in same block
56 inline int GetMinLeaderSize()
57 {
58 return (2*sizeof(ISIS_LONG)+4*sizeof(ISIS_INT));
59 }
60#else
61 //Length of Leader in master record
62 inline int GetLeaderSize()
63 {
64 return (2*sizeof(ISIS_LONG)+5*sizeof(ISIS_INT));
65 }
66 // Mini Leader length guaranteed to be in same block
67 inline int GetMinLeaderSize()
68 {
69 return (2*sizeof(ISIS_LONG)+3*sizeof(ISIS_INT));
70 }
71#endif
72
73// Size of Mfn and Mfrl in the leader part
74inline int GetSubLeaderSize() { return sizeof(ISIS_LONG)+sizeof(ISIS_INT); }
75
76inline int GetDirEntrySize() { return (3*sizeof(ISIS_INT)); }
77
78
79const TCHAR SYSRSEP = TCHAR('%'); // Repeatable field separator
80const TCHAR SUBFIELD_SEP = TCHAR('^'); // Subfield separator
81
82////////////////////////////////////////
83// Directory entry aggregate structure
84//
85struct DirEntry
86{
87 ISIS_INT tag_;
88 ISIS_INT pos_;
89 ISIS_INT len_;
90 DirEntry()
91 : tag_(0), pos_(0), len_ (0) { }
92
93 DirEntry(ISIS_INT tag, ISIS_INT pos, ISIS_INT len)
94 : tag_(tag), pos_(pos), len_ (len) { }
95 bool operator==(const DirEntry& rhs) const
96 {
97 if (tag_!=rhs.tag_ || pos_!=rhs.pos_ || len_!=rhs.len_)
98 return false;
99 return true;
100 }
101 bool operator!=(const DirEntry& rhs) const
102 {
103 if (tag_!=rhs.tag_ || pos_!=rhs.pos_ || len_!=rhs.len_)
104 return true;
105 return false;
106 }
107
108};
109
110
111//////////////////////////////////////////////////////////////////////////
112// Data Master record aggregate structure
113//
114struct LeaderAndDirectory
115{
116 ISIS_LONG mfn_; // Master file number
117 ISIS_INT mfrl_; // Record length
118 ISIS_LONG mfbwb_; // Backward pointer block number
119 ISIS_INT mfbwp_; // Backward pointer offset
120 ISIS_INT base_; // Offset to begining of variable fields
121 ISIS_INT nvf_; // Number of directory entries
122 ISIS_INT status_; // 1 = DELETED
123 std::vector<DirEntry> dir_; // Directory
124
125 LeaderAndDirectory()
126 {
127 Clear();
128 }
129 LeaderAndDirectory(const LeaderAndDirectory& src)
130 {
131 Copy(src);
132 }
133
134 LeaderAndDirectory& operator=(const LeaderAndDirectory& rhs)
135 {
136 if (&mfn_ != &rhs.mfn_)
137 {
138 Copy(rhs);
139 }
140 return *this;
141 }
142
143 void Copy(const LeaderAndDirectory& rhs)
144 {
145 mfn_ = rhs.mfn_;
146 mfrl_ = rhs.mfrl_;
147 mfbwb_ = rhs.mfbwb_;
148 mfbwp_ = rhs.mfbwp_;
149 base_ = rhs.base_;
150 nvf_ = rhs.nvf_;
151 status_ = rhs.status_;
152 dir_ = rhs.dir_;
153 }
154 void Clear()
155 {
156 mfn_ = mfrl_ = mfbwb_ = mfbwp_ = base_ = nvf_ = status_ = 0;
157 dir_.clear();
158 }
159
160 bool operator==(const LeaderAndDirectory& rhs) const;
161 bool operator!=(const LeaderAndDirectory& rhs) const;
162 int GetFieldSize();
163};
164
165cstringstream& operator<<(cstringstream& s, const LeaderAndDirectory& leader);
166cstringstream& operator>>(cstringstream& s, LeaderAndDirectory& leader);
167
168////////////////////////////////////////////////////////////
169//
170
171/////////////////////////////////
172// Data master file record class
173//
174
175typedef std::map<int, ustring> TAG2FIELD;
176class MfFile;
177class MstFile;
178class IsisDb;
179class ACE_InputCDR;
180class ACE_OutputCDR;
181class UMfRecord;
182
183
184class MfRecord
185{
186 friend class MfFile;
187 friend class MstFile;
188 friend class IsisDb;
189 friend class UMfRecord;
190 friend int operator>>(ACE_InputCDR& cdr, MfRecord& mfr);
191 friend int operator<<(ACE_OutputCDR& cdr, MfRecord& mfr);
192protected:
193
194 CFdt* pFdt_; // Use a copy of the FDT
195 cstring record_; // Record in continuous storage
196 // always as ANSI!
197
198 LeaderAndDirectory leader_directory_;
199
200 TAG2FIELD fields_;
201 std::vector<int> tags_;
202 static char m_buf[MFBLKSIZE]; // Buffer to hold 1 File block
203
204protected: // Additional data
205 short int state_; // Record state in memory
206 long mfb_read_; // Record was read at Block number [1...]
207 int mfp_read_; // Record was read at position in block
208 int mflen_read_; // Record length was when record read
209
210protected:
211 void Copy(const MfRecord& rhs);
212
213 void AddToRecord(const char* p, int len);
214 int AddDirEntry(const DirEntry& d);
215 int AddDirEntry(int tag, int pos, int len);
216 int DelDirEntry(int i);
217 void SetMfrl(int mfrl);
218 void SetMfbwb(long mfbwb);
219 void SetMfbwp(int mfbwp);
220 void SetBase(int base);
221 void SetNvf(int nvf);
222 void SetStatus(int s);
223 int SetDirEntry(int i, int tag, int pos, int len);
224 int SetDirEntry(int i, const DirEntry& d);
225 void SetMfbRead(long b);
226 void SetMfpRead(int pos);
227 void SetMflenRead(int len);
228
229
230 void SetSubLeaderAndDirectory(const char* p, int len);
231
232
233 void MakeTagToFieldMap();
234 void MakeTagVector();
235
236 long ComputeMfrl();
237
238 void Copy(UMfRecord& rhs);
239public:
240 enum { Record_Empty, Record_Read, Record_Changed, Record_Created };
241
242public:
243 //-----------------
244 // Public Interface
245 //-----------------
246 MfRecord(CFdt* pFdt=NULL); // Default constructor
247 virtual ~MfRecord(); // Destructor
248
249 MfRecord(const MfRecord& rhs); // Copy constructor
250 MfRecord& operator=(const MfRecord& rhs); // Assignment
251
252 MfRecord(const UMfRecord& umfr);
253 MfRecord& operator=(const UMfRecord& rhs);
254
255 void Clear();
256 void ClearData();
257
258
259 void ReadLeader(MfFile& f, long daddr);
260 bool Read (MfFile& f, long mfb, int mfp);
261 void Write(MfFile& f, long mfb, int mfp);
262
263 void MakeISORecord(std::string& s);
264
265 long GetMfn() const; // Get MFN
266 int GetMfrl() const; // Get Master File Record Length
267 long GetMfbwb() const; // Get Master File Backward Block number
268 int GetMfbwp() const; // Get Master File Backward block position
269 int GetBase() const; // Get Variable fields starting byte
270 int GetNvf() const; // Get Number of entries in the directory
271 int GetStatus() const; // Get Record Status
272 DirEntry GetDirEntry(int i) const; // Get a reference to the ieme directory entry
273 int GetState() const; // Get record state in memory
274 long GetMfbRead() const;
275 int GetMfpRead() const;
276 int GetMflenRead() const;
277
278 ustring GetAllFields(); // ANSI or UNICODE
279 cstring GetRecordAsString() { return record_; }
280 const char* GetRecord() { return record_.c_str(); }
281 int GetRecordLength() { return record_.length(); }
282
283 void ConvertToAnsi();
284
285
286 bool GetField(int tag, std::string& s); // Get field content for field with tag "tag"
287 bool AddField(int tag, std::string& s);
288 bool DeleteField(int tag);
289 bool ReplaceField(int tag, std::string& s);
290 bool AddOccurence(int tag, std::string& o);
291
292 int GetFieldTag(int i);
293 int GetFieldPos(int i);
294 int GetFieldLen(int i);
295
296 void SetMfn(long mfn);
297 void SetState(int s);
298
299 long GetDirectorySize();
300 int GetFieldSize() { return leader_directory_.GetFieldSize(); }
301
302 std::vector<int> GetFieldTags(); // Get tags of fields in increasing order,
303 // Occurences made only 1 field
304 void ExtractSubLeader();
305 void ExtractLeader();
306 bool CheckIntegrity();
307 bool CheckLeader();
308 bool CheckLeaderAndDirectory();
309
310 bool operator==(const MfRecord& rhs) const
311 {
312 return (record_ == rhs.record_);
313 }
314 bool operator!=(const MfRecord& rhs) const
315 {
316 return (record_ != rhs.record_);
317 }
318
319 void SetRecord(const char *s) { record_ = s; DecomposeRecord();}
320 void SetRecord(const cstring &s)
321 { record_ = s; DecomposeRecord();}
322 void ComposeRecord();
323 bool DecomposeRecord();
324
325 bool CheckRecord();
326 void Dump();
327} ;
328
329//////////////////////////////
330
331
332
333
334inline void MfRecord::AddToRecord(const char* p, int len)
335{
336 record_ += cstring(p,len);
337}
338
339/////////////////////////////
340
341inline MfRecord::MfRecord(CFdt* pFdt)
342// Makes a Master file Record object
343{
344 Clear();
345 pFdt_ = pFdt;
346 // Nothing more to do
347}
348
349inline void MfRecord::Copy(const MfRecord& rhs)
350{
351 record_ = rhs.record_;
352 leader_directory_ = rhs.leader_directory_;
353 fields_ = rhs.fields_;
354 state_ = rhs.state_;
355 mfb_read_ = rhs.mfb_read_;
356 mfp_read_ = rhs.mfp_read_;
357 mflen_read_ = rhs.mflen_read_;
358 tags_ = rhs.tags_;
359 pFdt_ = rhs.pFdt_;
360}
361
362inline MfRecord::MfRecord(const MfRecord& rhs) // Copy constructor
363{
364 Copy(rhs);
365}
366
367inline MfRecord& MfRecord::operator=(const MfRecord& rhs) // Assignment
368{
369 if (&leader_directory_ != &rhs.leader_directory_)
370 {
371 Copy(rhs);
372 }
373 return *this;
374}
375
376inline void MfRecord::Clear()
377{
378 tags_.clear();
379 record_.erase();
380 leader_directory_.Clear();
381 fields_.clear();
382 SetBase(GetLeaderSize());
383 SetMfrl(GetLeaderSize());
384 state_ = Record_Empty;
385 mfb_read_ = mfp_read_ = mflen_read_ = 0;
386 pFdt_ = NULL;
387}
388
389// Clear the data part but keep other info intact so that
390// it appears as an empty record
391inline void MfRecord::ClearData()
392{
393 tags_.clear();
394 record_.erase();
395 leader_directory_.Clear();
396 fields_.clear();
397 SetBase(GetLeaderSize());
398 SetMfrl(GetLeaderSize());
399}
400
401
402//////////////////////////////
403
404inline MfRecord::~MfRecord()
405{
406}
407
408//////////////////////////////
409
410inline long MfRecord::GetMfn() const
411// Returns Master file number
412{
413 return leader_directory_.mfn_;
414}
415
416//////////////////////////////
417
418inline int MfRecord::GetMfrl() const
419// Returns Master file record length
420{
421 return leader_directory_.mfrl_;
422}
423
424//////////////////////////////
425
426inline long MfRecord::GetMfbwb() const
427// Returns backward pointer block number
428{
429 return leader_directory_.mfbwb_;
430}
431
432//////////////////////////////
433
434inline int MfRecord::GetMfbwp() const
435// Returns backward pointer offset
436{
437 return leader_directory_.mfbwp_;
438}
439
440//////////////////////////////
441
442inline int MfRecord::GetBase() const
443// Returns base value to field data
444{
445 return leader_directory_.base_;
446}
447
448//////////////////////////////
449
450inline int MfRecord::GetNvf() const
451// Returns the number of directory entries
452// in the master file record
453{
454 return leader_directory_.nvf_;
455}
456
457//////////////////////////////
458
459inline int MfRecord::GetStatus() const
460// Returns the status of the record
461{
462 return leader_directory_.status_;
463}
464
465//////////////////////////////
466
467
468//////////////////////////////
469
470inline DirEntry MfRecord::GetDirEntry(int i) const
471// Returns the ith dir entry
472{
473 return leader_directory_.dir_[i];
474}
475
476//////////////////////////////
477
478inline int MfRecord::GetState() const
479{
480 return state_;
481}
482
483//////////////////////////////
484
485inline long MfRecord::GetMfbRead() const
486{
487 return mfb_read_;
488}
489//////////////////////////////
490
491inline int MfRecord::GetMfpRead() const
492{
493 return mfp_read_;
494}
495
496//////////////////////////////
497
498// Get tags of fields in increasing order,
499inline std::vector<int> MfRecord::GetFieldTags()
500{
501 PRECONDITION(tags_.size() == fields_.size());
502 return tags_;
503}
504//////////////////////////////
505
506inline int MfRecord::GetMflenRead() const
507{
508 return mflen_read_;
509}
510
511///////////////////////////////////////////////////////////////////////////////
512
513inline void MfRecord::SetMfn(long mfn)
514// Set Master file number
515{
516 assert(mfn>0);
517 leader_directory_.mfn_ = mfn;
518}
519//////////////////////////////
520
521inline void MfRecord::SetMfrl(int mfrl)
522// Set Master file record length
523{
524 assert(mfrl>0);
525 leader_directory_.mfrl_ = mfrl;
526}
527//////////////////////////////
528
529inline void MfRecord::SetMfbwb(long mfbwb)
530// Sets backward pointer block number to mfbwb
531{
532 assert(mfbwb>=0);
533 leader_directory_.mfbwb_ = mfbwb;
534}
535
536//////////////////////////////
537
538inline void MfRecord::SetMfbwp(int mfbwp)
539// Sets backward pointer block offset to mfbwp
540{
541 assert(mfbwp>=0);
542 leader_directory_.mfbwp_ = mfbwp;
543}
544//////////////////////////////
545
546inline void MfRecord::SetBase(int base)
547// Sets the base value in the record aggregate
548{
549 assert(base>=0);
550 leader_directory_.base_ = base;
551}
552
553//////////////////////////////
554
555inline void MfRecord::SetNvf(int nvf)
556// Sets the number of entries in the directory part
557{
558 assert(nvf>=0);
559 leader_directory_.nvf_ = nvf;
560}
561
562//////////////////////////////
563
564inline void MfRecord::SetStatus(int s)
565// Sets the status of the record
566{
567 leader_directory_.status_ = s;
568}
569
570//////////////////////////////
571
572inline void MfRecord::SetState(int s)
573// Sets the status of the record
574{
575 assert(s==MfRecord::Record_Empty || s==MfRecord::Record_Read
576 || s==MfRecord::Record_Changed || s==MfRecord::Record_Created);
577 state_ = s;
578}
579
580inline void MfRecord::SetMfbRead(long b)
581{
582 mfb_read_ = b;
583}
584
585inline void MfRecord::SetMfpRead(int pos)
586{
587 mfp_read_ = pos;
588}
589
590inline void MfRecord::SetMflenRead(int len)
591{
592 mflen_read_ = len;
593}
594
595inline int MfRecord::GetFieldTag(int i)
596{
597 return leader_directory_.dir_[i].tag_;
598}
599inline int MfRecord::GetFieldPos(int i)
600{
601 return leader_directory_.dir_[i].pos_;
602}
603
604inline int MfRecord::GetFieldLen(int i)
605{
606 return leader_directory_.dir_[i].len_;
607}
608
609#endif
Note: See TracBrowser for help on using the repository browser.