1 //
2 // This file is part of the SDTS++ toolkit, written by the U.S.
3 // Geological Survey.  It is experimental software, written to support
4 // USGS research and cartographic data production.
5 //
6 // SDTS++ is public domain software.  It may be freely copied,
7 // distributed, and modified.  The USGS welcomes user feedback, but makes
8 // no committment to any level of support for this code.  See the SDTS
9 // web site at http://mcmcweb.er.usgs.gov/sdts for more information,
10 // including points of contact.
11 //
12 //
13 // $Id: sc_Subfield.h,v 1.10 2003/01/03 20:41:05 mcoletti Exp $
14 //
15 
16 #ifndef INCLUDED_SCSUBFIELD_HXX
17 #define INCLUDED_SCSUBFIELD_HXX
18 
19 #include <iostream>
20 #include <string>
21 
22 #ifndef INCLUDED_SCMULTITYPEVALUE_HXX
23 #include <sdts++/container/sc_MultiTypeValue.h>
24 #endif
25 
26 
27 
28 /**
29    \note
30 
31          * Attribute subfields should have their mnemonic set to
32          either "ATTP" or "ATTS", and their name set to the actual
33          name of the attribute. Non- attribute subfields should have
34          their mnemonic set to one of the subfield mnemonics defined
35          by the SDTS. The name of a non-attribute subfield does not
36          have to be set, and will not be if read from a transfer.
37 
38          Also, it's possible for a subfield to have a type, but have
39          no value.  A subfield starts out this by default and can be
40          set to this null state via the setUnvalued() member.  This
41          is useful if you have to have a 'placeholder' subfield in
42          an sc_Record that doesn't have any value at all.
43 
44    This class represents an SDTS Subfield. A Subfield has a value
45    that is one of several types.
46 
47    Using one of the 'set' methods sets both the value *and* the
48    type.  There is no way to set a value without setting the
49    type. There is no way to "lock" the type; setting an instance to
50    a new value with a different type will change the type associated
51    with the instance.  This models the behavior of a variable whose
52    type has run-time binding.  The type of the variable depends on
53    the type of the value assigned to it.
54 
55    'get'ting the value of an instance will fail unless the member
56    function corresponding to the current type of the instance is
57    used.  For example, getting a string value for a subfield set as
58    a BI32 will fail.
59 
60    An SDTS Subfield has the following attributes:
61       Type:
62          "The Data Type shall indicate the manner in which the subfield
63          shall be encoded." -- The SDTS, section 4.2.1 "Specification Layout".
64          The data type is one of:
65             A: graphic characters, alphanumeric characters, or
66                alphabetic characters.
67             I: implicit-point (integer)
68             R: explicit-point unscaled (fixed point real)
69             S: explicit-point scaled (floating point real)
70             B: bitfield data
71             C: character mode bitfield (binary in zero and one characters)
72 
73          The 'B' type may have additional qualification as follows:
74             BI8:    8 bit signed integer
75             BI16:   16 bit signed integer
76             BI24:   24 bit signed integer
77             BI32:   32 bit signed integer
78             BUI:    unsigned integer, length specified by implementation
79             BUI8:   8 bit unsigned integer
80             BUI16:  16 bit unsigned integer
81             BUI24:  24 bit unsigned integer
82             BUI32:  32 bit unsigned integer
83             BFP32:  32 bit floating point real
84             BFP64:  64 bit floating point real
85 
86          In an sc_Subfield, the types listed above are actually
87          stored using one of long, unsigned long, double, string or
88          vector<char>. The mapping from SDTS data type to C++ is as
89          follows:
90 
91             A                            string
92             I                            long
93             R,S                          double
94             C                            Not Implemented
95             BUI                          Not Implemented
96             BI8, BI16, BI24, BI32        long
97             BUI8, BUI16, BUI24, BUI32    unsigned long
98             BFP32                        float
99             BFP64                        double
100 
101       Value:
102          The actual value stored in the Subfield.
103 
104       Name:
105          A string representing the subfield name ("Module Name",
106          "Record ID", etc).
107 
108       Mnemonic:
109          A string representing the subfield mnemonic ("MODN", "RCID", etc).
110 
111 
112 
113 */
114 class sc_Subfield
115 {
116    public:
117 
118       /// Denotes a subfield's type.
119       enum SubfieldType { is_A,
120                           is_I,
121                           is_R,
122                           is_S,
123                           is_C,
124                           is_B,
125                           is_BI8,
126                           is_BI16,
127                           is_BI24,
128                           is_BI32,
129                           is_BUI,
130                           is_BUI8,
131                           is_BUI16,
132                           is_BUI24,
133                           is_BUI32,
134                           is_BFP32,
135                           is_BFP64
136       };
137 
138       ///
139       sc_Subfield();
140 
141       ///
142       sc_Subfield( std::string const& name, std::string const& mnemonic );
143 
144       ///
145       sc_Subfield(sc_Subfield const& right);
146 
147       ///
148       ~sc_Subfield();
149 
150       ///
151       sc_Subfield& operator=(sc_Subfield const& right);
152 
153       ///
154       bool operator==(sc_Subfield const& right) const;
155 
156       ///
157       bool operator!=(sc_Subfield const& right) const;
158 
159       ///
160       SubfieldType getSubfieldType() const;
161 
162       /// Returns the SDTS Name of this subfield (if one has been set).
163       std::string const& getName() const;
164 
165       /// abbreviation for getName()
name()166       std::string const &name() const { return getName(); }
167 
168       /// Returns the SDTS Mnemonic of this subfield (if one has been set).
169       std::string const& getMnemonic() const;
170 
171       /// abbreviation for getMnemonic()
mnemonic()172       std::string const& mnemonic() const { return getMnemonic(); }
173 
174       ///
175       bool getA(std::string& val) const;
176 
177       ///
178       bool getI(long& val) const;
179 
180       ///
181       bool getR(double& val) const;
182 
183       ///
184       bool getS(double& val) const;
185 
186       ///
187       bool getC(std::string& val) const;
188 
189       ///
190       bool getBI8(long& val) const;
191 
192       ///
193       bool getBI16(long& val) const;
194 
195       ///
196       bool getBI24(long& val) const;
197 
198       ///
199       bool getBI32(long& val) const;
200 
201       ///
202       bool getBUI8(unsigned long& val) const;
203 
204       ///
205       bool getBUI16(unsigned long& val) const;
206 
207       ///
208       bool getBUI24(unsigned long& val) const;
209 
210       ///
211       bool getBUI32(unsigned long& val) const;
212 
213       // bool getB(xyzzy) const;      // Not Implemented.
214 
215       ///
216       bool getBFP32(float& val) const;
217 
218       ///
219       bool getBFP64(double& val) const;
220 
221       /// convert the value to an integer, returning false if the underlying type doesn't support it
222       /**
223          The is a convenience member function to spare the programmer
224          from having to go through a variety of machinations to first
225          check the type, then use a variable of the correct type, use
226          it, then convert it back to the target type.  That's all just
227          silly.  So I do it all here for you.
228 
229       */
230       bool getInt( int & val ) const;
231 
232 
233       /// convert the value to a real, returning false if the underlying type doesn't support it
234       /**
235          The is a convenience member function to spare the programmer
236          from having to go through a variety of machinations to first
237          check the type, then use a variable of the correct type, use
238          it, then convert it back to the target type.  That's all just
239          silly.  So I do it all here for you.
240 
241       */
242       bool getFloat( float & val ) const;
243 
244 
245 
246       /// convert the value to a real, returning false if the underlying type doesn't support it
247       /**
248          The is a convenience member function to spare the programmer
249          from having to go through a variety of machinations to first
250          check the type, then use a variable of the correct type, use
251          it, then convert it back to the target type.  That's all just
252          silly.  So I do it all here for you.
253 
254       */
255       bool getDouble( double & val ) const;
256 
257       /**
258        Returns the 'value' of the subfield in an object that can be
259        one of several different types.
260        SlUtils defines functions for extracting specific
261        C++ types from a sc_Subfield using this member function.
262        (For example, see: SlUtils::getDoubleFromSubfield()) */
263       sc_MultiTypeValue const& getValue() const;
264 
265       ///
266       std::string const& setName(std::string const& name);
name(std::string const & name)267       std::string const& name(std::string const& name) { return setName(name); }
268 
269       ///
270       std::string const& setMnemonic(std::string const& mnem);
mnemonic(std::string const & mnem)271       std::string const& mnemonic(std::string const& mnem) { return setMnemonic(mnem); }
272 
273       //@{
274       /// set the subfield to the given value and lock it into its type
275       void setA(std::string const& val);
276       void setI(long val);
277       void setR(double val);
278       void setS(double val);
279       void setC(std::string const& val);
280       // void setB(xyzzy);      // NOT IMPLEMENTED.
281       void setBI8(long val);
282       void setBI16(long val);
283       void setBI24(long val);
284       void setBI32(long val);
285       void setBUI8(unsigned long val);
286       void setBUI16(unsigned long val);
287       void setBUI24(unsigned long val);
288       void setBUI32(unsigned long val);
289       void setBFP32(float val);
290       void setBFP64(double val);
291       //@}
292 
293       /**
294        This resets the subfield back to a 'uninitialized' state such that
295        it still has a type, but no value.
296       */
297       void setUnvalued();
298 
299       /// returns true if the subfield has no value and associated type
isUnvalued()300       bool isUnvalued() const { return value_.null(); }
301 
302    private:
303 
304       /// SDTS Subfield Name
305       std::string name_;
306 
307       /// SDTS Subfield Mnemonic
308       std::string mnemonic_;
309 
310       ///
311       sc_MultiTypeValue value_;
312 
313       ///
314       SubfieldType type_;
315 
316       friend std::ostream& operator<<(std::ostream&, sc_Subfield const&);
317 
318 }; // class sc_Subfield
319 
320 
321 
322 #endif  // INCLUDED_SCSUBFIELD_HXX
323