• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 ********************************************************************************
5 *   Copyright (C) 1997-2014, International Business Machines
6 *   Corporation and others.  All Rights Reserved.
7 ********************************************************************************
8 *
9 * File FMTABLE.H
10 *
11 * Modification History:
12 *
13 *   Date        Name        Description
14 *   02/29/97    aliu        Creation.
15 ********************************************************************************
16 */
17 #ifndef FMTABLE_H
18 #define FMTABLE_H
19 
20 #include "unicode/utypes.h"
21 
22 /**
23  * \file
24  * \brief C++ API: Formattable is a thin wrapper for primitive types used for formatting and parsing
25  */
26 
27 #if !UCONFIG_NO_FORMATTING
28 
29 #include "unicode/unistr.h"
30 #include "unicode/stringpiece.h"
31 #include "unicode/uformattable.h"
32 
33 U_NAMESPACE_BEGIN
34 
35 class CharString;
36 namespace number {
37 namespace impl {
38 class DecimalQuantity;
39 }
40 }
41 
42 /**
43  * Formattable objects can be passed to the Format class or
44  * its subclasses for formatting.  Formattable is a thin wrapper
45  * class which interconverts between the primitive numeric types
46  * (double, long, etc.) as well as UDate and UnicodeString.
47  *
48  * <p>Internally, a Formattable object is a union of primitive types.
49  * As such, it can only store one flavor of data at a time.  To
50  * determine what flavor of data it contains, use the getType method.
51  *
52  * <p>As of ICU 3.0, Formattable may also wrap a UObject pointer,
53  * which it owns.  This allows an instance of any ICU class to be
54  * encapsulated in a Formattable.  For legacy reasons and for
55  * efficiency, primitive numeric types are still stored directly
56  * within a Formattable.
57  *
58  * <p>The Formattable class is not suitable for subclassing.
59  *
60  * <p>See UFormattable for a C wrapper.
61  */
62 class U_I18N_API Formattable : public UObject {
63 public:
64     /**
65      * This enum is only used to let callers distinguish between
66      * the Formattable(UDate) constructor and the Formattable(double)
67      * constructor; the compiler cannot distinguish the signatures,
68      * since UDate is currently typedefed to be either double or long.
69      * If UDate is changed later to be a bonafide class
70      * or struct, then we no longer need this enum.
71      * @stable ICU 2.4
72      */
73     enum ISDATE { kIsDate };
74 
75     /**
76      * Default constructor
77      * @stable ICU 2.4
78      */
79     Formattable(); // Type kLong, value 0
80 
81     /**
82      * Creates a Formattable object with a UDate instance.
83      * @param d the UDate instance.
84      * @param flag the flag to indicate this is a date. Always set it to kIsDate
85      * @stable ICU 2.0
86      */
87     Formattable(UDate d, ISDATE flag);
88 
89     /**
90      * Creates a Formattable object with a double number.
91      * @param d the double number.
92      * @stable ICU 2.0
93      */
94     Formattable(double d);
95 
96     /**
97      * Creates a Formattable object with a long number.
98      * @param l the long number.
99      * @stable ICU 2.0
100      */
101     Formattable(int32_t l);
102 
103     /**
104      * Creates a Formattable object with an int64_t number
105      * @param ll the int64_t number.
106      * @stable ICU 2.8
107      */
108     Formattable(int64_t ll);
109 
110 #if !UCONFIG_NO_CONVERSION
111     /**
112      * Creates a Formattable object with a char string pointer.
113      * Assumes that the char string is null terminated.
114      * @param strToCopy the char string.
115      * @stable ICU 2.0
116      */
117     Formattable(const char* strToCopy);
118 #endif
119 
120     /**
121      * Creates a Formattable object of an appropriate numeric type from a
122      * a decimal number in string form.  The Formattable will retain the
123      * full precision of the input in decimal format, even when it exceeds
124      * what can be represented by a double or int64_t.
125      *
126      * @param number  the unformatted (not localized) string representation
127      *                     of the Decimal number.
128      * @param status  the error code.  Possible errors include U_INVALID_FORMAT_ERROR
129      *                if the format of the string does not conform to that of a
130      *                decimal number.
131      * @stable ICU 4.4
132      */
133     Formattable(StringPiece number, UErrorCode &status);
134 
135     /**
136      * Creates a Formattable object with a UnicodeString object to copy from.
137      * @param strToCopy the UnicodeString string.
138      * @stable ICU 2.0
139      */
140     Formattable(const UnicodeString& strToCopy);
141 
142     /**
143      * Creates a Formattable object with a UnicodeString object to adopt from.
144      * @param strToAdopt the UnicodeString string.
145      * @stable ICU 2.0
146      */
147     Formattable(UnicodeString* strToAdopt);
148 
149     /**
150      * Creates a Formattable object with an array of Formattable objects.
151      * @param arrayToCopy the Formattable object array.
152      * @param count the array count.
153      * @stable ICU 2.0
154      */
155     Formattable(const Formattable* arrayToCopy, int32_t count);
156 
157     /**
158      * Creates a Formattable object that adopts the given UObject.
159      * @param objectToAdopt the UObject to set this object to
160      * @stable ICU 3.0
161      */
162     Formattable(UObject* objectToAdopt);
163 
164     /**
165      * Copy constructor.
166      * @stable ICU 2.0
167      */
168     Formattable(const Formattable&);
169 
170     /**
171      * Assignment operator.
172      * @param rhs   The Formattable object to copy into this object.
173      * @stable ICU 2.0
174      */
175     Formattable&    operator=(const Formattable &rhs);
176 
177     /**
178      * Equality comparison.
179      * @param other    the object to be compared with.
180      * @return        TRUE if other are equal to this, FALSE otherwise.
181      * @stable ICU 2.0
182      */
183     UBool          operator==(const Formattable &other) const;
184 
185     /**
186      * Equality operator.
187      * @param other    the object to be compared with.
188      * @return        TRUE if other are unequal to this, FALSE otherwise.
189      * @stable ICU 2.0
190      */
191     UBool          operator!=(const Formattable& other) const
192       { return !operator==(other); }
193 
194     /**
195      * Destructor.
196      * @stable ICU 2.0
197      */
198     virtual         ~Formattable();
199 
200     /**
201      * Clone this object.
202      * Clones can be used concurrently in multiple threads.
203      * If an error occurs, then NULL is returned.
204      * The caller must delete the clone.
205      *
206      * @return a clone of this object
207      *
208      * @see getDynamicClassID
209      * @stable ICU 2.8
210      */
211     Formattable *clone() const;
212 
213     /**
214      * Selector for flavor of data type contained within a
215      * Formattable object.  Formattable is a union of several
216      * different types, and at any time contains exactly one type.
217      * @stable ICU 2.4
218      */
219     enum Type {
220         /**
221          * Selector indicating a UDate value.  Use getDate to retrieve
222          * the value.
223          * @stable ICU 2.4
224          */
225         kDate,
226 
227         /**
228          * Selector indicating a double value.  Use getDouble to
229          * retrieve the value.
230          * @stable ICU 2.4
231          */
232         kDouble,
233 
234         /**
235          * Selector indicating a 32-bit integer value.  Use getLong to
236          * retrieve the value.
237          * @stable ICU 2.4
238          */
239         kLong,
240 
241         /**
242          * Selector indicating a UnicodeString value.  Use getString
243          * to retrieve the value.
244          * @stable ICU 2.4
245          */
246         kString,
247 
248         /**
249          * Selector indicating an array of Formattables.  Use getArray
250          * to retrieve the value.
251          * @stable ICU 2.4
252          */
253         kArray,
254 
255         /**
256          * Selector indicating a 64-bit integer value.  Use getInt64
257          * to retrieve the value.
258          * @stable ICU 2.8
259          */
260         kInt64,
261 
262         /**
263          * Selector indicating a UObject value.  Use getObject to
264          * retrieve the value.
265          * @stable ICU 3.0
266          */
267         kObject
268    };
269 
270     /**
271      * Gets the data type of this Formattable object.
272      * @return    the data type of this Formattable object.
273      * @stable ICU 2.0
274      */
275     Type            getType(void) const;
276 
277     /**
278      * Returns TRUE if the data type of this Formattable object
279      * is kDouble, kLong, or kInt64
280      * @return TRUE if this is a pure numeric object
281      * @stable ICU 3.0
282      */
283     UBool           isNumeric() const;
284 
285     /**
286      * Gets the double value of this object. If this object is not of type
287      * kDouble then the result is undefined.
288      * @return    the double value of this object.
289      * @stable ICU 2.0
290      */
getDouble(void)291     double          getDouble(void) const { return fValue.fDouble; }
292 
293     /**
294      * Gets the double value of this object. If this object is of type
295      * long, int64 or Decimal Number then a conversion is peformed, with
296      * possible loss of precision.  If the type is kObject and the
297      * object is a Measure, then the result of
298      * getNumber().getDouble(status) is returned.  If this object is
299      * neither a numeric type nor a Measure, then 0 is returned and
300      * the status is set to U_INVALID_FORMAT_ERROR.
301      * @param status the error code
302      * @return the double value of this object.
303      * @stable ICU 3.0
304      */
305     double          getDouble(UErrorCode& status) const;
306 
307     /**
308      * Gets the long value of this object. If this object is not of type
309      * kLong then the result is undefined.
310      * @return    the long value of this object.
311      * @stable ICU 2.0
312      */
getLong(void)313     int32_t         getLong(void) const { return (int32_t)fValue.fInt64; }
314 
315     /**
316      * Gets the long value of this object. If the magnitude is too
317      * large to fit in a long, then the maximum or minimum long value,
318      * as appropriate, is returned and the status is set to
319      * U_INVALID_FORMAT_ERROR.  If this object is of type kInt64 and
320      * it fits within a long, then no precision is lost.  If it is of
321      * type kDouble, then a conversion is peformed, with
322      * truncation of any fractional part.  If the type is kObject and
323      * the object is a Measure, then the result of
324      * getNumber().getLong(status) is returned.  If this object is
325      * neither a numeric type nor a Measure, then 0 is returned and
326      * the status is set to U_INVALID_FORMAT_ERROR.
327      * @param status the error code
328      * @return    the long value of this object.
329      * @stable ICU 3.0
330      */
331     int32_t         getLong(UErrorCode& status) const;
332 
333     /**
334      * Gets the int64 value of this object. If this object is not of type
335      * kInt64 then the result is undefined.
336      * @return    the int64 value of this object.
337      * @stable ICU 2.8
338      */
getInt64(void)339     int64_t         getInt64(void) const { return fValue.fInt64; }
340 
341     /**
342      * Gets the int64 value of this object. If this object is of a numeric
343      * type and the magnitude is too large to fit in an int64, then
344      * the maximum or minimum int64 value, as appropriate, is returned
345      * and the status is set to U_INVALID_FORMAT_ERROR.  If the
346      * magnitude fits in an int64, then a casting conversion is
347      * peformed, with truncation of any fractional part.  If the type
348      * is kObject and the object is a Measure, then the result of
349      * getNumber().getDouble(status) is returned.  If this object is
350      * neither a numeric type nor a Measure, then 0 is returned and
351      * the status is set to U_INVALID_FORMAT_ERROR.
352      * @param status the error code
353      * @return    the int64 value of this object.
354      * @stable ICU 3.0
355      */
356     int64_t         getInt64(UErrorCode& status) const;
357 
358     /**
359      * Gets the Date value of this object. If this object is not of type
360      * kDate then the result is undefined.
361      * @return    the Date value of this object.
362      * @stable ICU 2.0
363      */
getDate()364     UDate           getDate() const { return fValue.fDate; }
365 
366     /**
367      * Gets the Date value of this object.  If the type is not a date,
368      * status is set to U_INVALID_FORMAT_ERROR and the return value is
369      * undefined.
370      * @param status the error code.
371      * @return    the Date value of this object.
372      * @stable ICU 3.0
373      */
374      UDate          getDate(UErrorCode& status) const;
375 
376     /**
377      * Gets the string value of this object. If this object is not of type
378      * kString then the result is undefined.
379      * @param result    Output param to receive the Date value of this object.
380      * @return          A reference to 'result'.
381      * @stable ICU 2.0
382      */
getString(UnicodeString & result)383     UnicodeString&  getString(UnicodeString& result) const
384       { result=*fValue.fString; return result; }
385 
386     /**
387      * Gets the string value of this object. If the type is not a
388      * string, status is set to U_INVALID_FORMAT_ERROR and a bogus
389      * string is returned.
390      * @param result    Output param to receive the Date value of this object.
391      * @param status    the error code.
392      * @return          A reference to 'result'.
393      * @stable ICU 3.0
394      */
395     UnicodeString&  getString(UnicodeString& result, UErrorCode& status) const;
396 
397     /**
398      * Gets a const reference to the string value of this object. If
399      * this object is not of type kString then the result is
400      * undefined.
401      * @return   a const reference to the string value of this object.
402      * @stable ICU 2.0
403      */
404     inline const UnicodeString& getString(void) const;
405 
406     /**
407      * Gets a const reference to the string value of this object.  If
408      * the type is not a string, status is set to
409      * U_INVALID_FORMAT_ERROR and the result is a bogus string.
410      * @param status    the error code.
411      * @return   a const reference to the string value of this object.
412      * @stable ICU 3.0
413      */
414     const UnicodeString& getString(UErrorCode& status) const;
415 
416     /**
417      * Gets a reference to the string value of this object. If this
418      * object is not of type kString then the result is undefined.
419      * @return   a reference to the string value of this object.
420      * @stable ICU 2.0
421      */
422     inline UnicodeString& getString(void);
423 
424     /**
425      * Gets a reference to the string value of this object. If the
426      * type is not a string, status is set to U_INVALID_FORMAT_ERROR
427      * and the result is a bogus string.
428      * @param status    the error code.
429      * @return   a reference to the string value of this object.
430      * @stable ICU 3.0
431      */
432     UnicodeString& getString(UErrorCode& status);
433 
434     /**
435      * Gets the array value and count of this object. If this object
436      * is not of type kArray then the result is undefined.
437      * @param count    fill-in with the count of this object.
438      * @return         the array value of this object.
439      * @stable ICU 2.0
440      */
getArray(int32_t & count)441     const Formattable* getArray(int32_t& count) const
442       { count=fValue.fArrayAndCount.fCount; return fValue.fArrayAndCount.fArray; }
443 
444     /**
445      * Gets the array value and count of this object. If the type is
446      * not an array, status is set to U_INVALID_FORMAT_ERROR, count is
447      * set to 0, and the result is NULL.
448      * @param count    fill-in with the count of this object.
449      * @param status the error code.
450      * @return         the array value of this object.
451      * @stable ICU 3.0
452      */
453     const Formattable* getArray(int32_t& count, UErrorCode& status) const;
454 
455     /**
456      * Accesses the specified element in the array value of this
457      * Formattable object. If this object is not of type kArray then
458      * the result is undefined.
459      * @param index the specified index.
460      * @return the accessed element in the array.
461      * @stable ICU 2.0
462      */
463     Formattable&    operator[](int32_t index) { return fValue.fArrayAndCount.fArray[index]; }
464 
465     /**
466      * Returns a pointer to the UObject contained within this
467      * formattable, or NULL if this object does not contain a UObject.
468      * @return a UObject pointer, or NULL
469      * @stable ICU 3.0
470      */
471     const UObject*  getObject() const;
472 
473     /**
474      * Returns a numeric string representation of the number contained within this
475      * formattable, or NULL if this object does not contain numeric type.
476      * For values obtained by parsing, the returned decimal number retains
477      * the full precision and range of the original input, unconstrained by
478      * the limits of a double floating point or a 64 bit int.
479      *
480      * This function is not thread safe, and therfore is not declared const,
481      * even though it is logically const.
482      *
483      * Possible errors include U_MEMORY_ALLOCATION_ERROR, and
484      * U_INVALID_STATE if the formattable object has not been set to
485      * a numeric type.
486      *
487      * @param status the error code.
488      * @return the unformatted string representation of a number.
489      * @stable ICU 4.4
490      */
491     StringPiece getDecimalNumber(UErrorCode &status);
492 
493      /**
494      * Sets the double value of this object and changes the type to
495      * kDouble.
496      * @param d    the new double value to be set.
497      * @stable ICU 2.0
498      */
499     void            setDouble(double d);
500 
501     /**
502      * Sets the long value of this object and changes the type to
503      * kLong.
504      * @param l    the new long value to be set.
505      * @stable ICU 2.0
506      */
507     void            setLong(int32_t l);
508 
509     /**
510      * Sets the int64 value of this object and changes the type to
511      * kInt64.
512      * @param ll    the new int64 value to be set.
513      * @stable ICU 2.8
514      */
515     void            setInt64(int64_t ll);
516 
517     /**
518      * Sets the Date value of this object and changes the type to
519      * kDate.
520      * @param d    the new Date value to be set.
521      * @stable ICU 2.0
522      */
523     void            setDate(UDate d);
524 
525     /**
526      * Sets the string value of this object and changes the type to
527      * kString.
528      * @param stringToCopy    the new string value to be set.
529      * @stable ICU 2.0
530      */
531     void            setString(const UnicodeString& stringToCopy);
532 
533     /**
534      * Sets the array value and count of this object and changes the
535      * type to kArray.
536      * @param array    the array value.
537      * @param count    the number of array elements to be copied.
538      * @stable ICU 2.0
539      */
540     void            setArray(const Formattable* array, int32_t count);
541 
542     /**
543      * Sets and adopts the string value and count of this object and
544      * changes the type to kArray.
545      * @param stringToAdopt    the new string value to be adopted.
546      * @stable ICU 2.0
547      */
548     void            adoptString(UnicodeString* stringToAdopt);
549 
550     /**
551      * Sets and adopts the array value and count of this object and
552      * changes the type to kArray.
553      * @stable ICU 2.0
554      */
555     void            adoptArray(Formattable* array, int32_t count);
556 
557     /**
558      * Sets and adopts the UObject value of this object and changes
559      * the type to kObject.  After this call, the caller must not
560      * delete the given object.
561      * @param objectToAdopt the UObject value to be adopted
562      * @stable ICU 3.0
563      */
564     void            adoptObject(UObject* objectToAdopt);
565 
566     /**
567      * Sets the the numeric value from a decimal number string, and changes
568      * the type to to a numeric type appropriate for the number.
569      * The syntax of the number is a "numeric string"
570      * as defined in the Decimal Arithmetic Specification, available at
571      * http://speleotrove.com/decimal
572      * The full precision and range of the input number will be retained,
573      * even when it exceeds what can be represented by a double or an int64.
574      *
575      * @param numberString  a string representation of the unformatted decimal number.
576      * @param status        the error code.  Set to U_INVALID_FORMAT_ERROR if the
577      *                      incoming string is not a valid decimal number.
578      * @stable ICU 4.4
579      */
580     void             setDecimalNumber(StringPiece numberString,
581                                       UErrorCode &status);
582 
583     /**
584      * ICU "poor man's RTTI", returns a UClassID for the actual class.
585      *
586      * @stable ICU 2.2
587      */
588     virtual UClassID getDynamicClassID() const;
589 
590     /**
591      * ICU "poor man's RTTI", returns a UClassID for this class.
592      *
593      * @stable ICU 2.2
594      */
595     static UClassID U_EXPORT2 getStaticClassID();
596 
597     /**
598      * Convert the UFormattable to a Formattable.  Internally, this is a reinterpret_cast.
599      * @param fmt a valid UFormattable
600      * @return the UFormattable as a Formattable object pointer.  This is an alias to the original
601      * UFormattable, and so is only valid while the original argument remains in scope.
602      * @stable ICU 52
603      */
604     static inline Formattable *fromUFormattable(UFormattable *fmt);
605 
606     /**
607      * Convert the const UFormattable to a const Formattable.  Internally, this is a reinterpret_cast.
608      * @param fmt a valid UFormattable
609      * @return the UFormattable as a Formattable object pointer.  This is an alias to the original
610      * UFormattable, and so is only valid while the original argument remains in scope.
611      * @stable ICU 52
612      */
613     static inline const Formattable *fromUFormattable(const UFormattable *fmt);
614 
615     /**
616      * Convert this object pointer to a UFormattable.
617      * @return this object as a UFormattable pointer.   This is an alias to this object,
618      * and so is only valid while this object remains in scope.
619      * @stable ICU 52
620      */
621     inline UFormattable *toUFormattable();
622 
623     /**
624      * Convert this object pointer to a UFormattable.
625      * @return this object as a UFormattable pointer.   This is an alias to this object,
626      * and so is only valid while this object remains in scope.
627      * @stable ICU 52
628      */
629     inline const UFormattable *toUFormattable() const;
630 
631 #ifndef U_HIDE_DEPRECATED_API
632     /**
633      * Deprecated variant of getLong(UErrorCode&).
634      * @param status the error code
635      * @return the long value of this object.
636      * @deprecated ICU 3.0 use getLong(UErrorCode&) instead
637      */
638     inline int32_t getLong(UErrorCode* status) const;
639 #endif  /* U_HIDE_DEPRECATED_API */
640 
641 #ifndef U_HIDE_INTERNAL_API
642     /**
643      * Internal function, do not use.
644      * TODO:  figure out how to make this be non-public.
645      *        NumberFormat::format(Formattable, ...
646      *        needs to get at the DecimalQuantity, if it exists, for
647      *        big decimal formatting.
648      *  @internal
649      */
getDecimalQuantity()650     number::impl::DecimalQuantity *getDecimalQuantity() const { return fDecimalQuantity;}
651 
652     /**
653      * Export the value of this Formattable to a DecimalQuantity.
654      * @internal
655      */
656     void populateDecimalQuantity(number::impl::DecimalQuantity& output, UErrorCode& status) const;
657 
658     /**
659      *  Adopt, and set value from, a DecimalQuantity
660      *     Internal Function, do not use.
661      *  @param dq the DecimalQuantity to be adopted
662      *  @internal
663      */
664     void adoptDecimalQuantity(number::impl::DecimalQuantity *dq);
665 
666     /**
667      * Internal function to return the CharString pointer.
668      * @param status error code
669      * @return pointer to the CharString - may become invalid if the object is modified
670      * @internal
671      */
672     CharString *internalGetCharString(UErrorCode &status);
673 
674 #endif  /* U_HIDE_INTERNAL_API */
675 
676 private:
677     /**
678      * Cleans up the memory for unwanted values.  For example, the adopted
679      * string or array objects.
680      */
681     void            dispose(void);
682 
683     /**
684      * Common initialization, for use by constructors.
685      */
686     void            init();
687 
688     UnicodeString* getBogus() const;
689 
690     union {
691         UObject*        fObject;
692         UnicodeString*  fString;
693         double          fDouble;
694         int64_t         fInt64;
695         UDate           fDate;
696         struct {
697           Formattable*  fArray;
698           int32_t       fCount;
699         }               fArrayAndCount;
700     } fValue;
701 
702     CharString           *fDecimalStr;
703 
704     number::impl::DecimalQuantity *fDecimalQuantity;
705 
706     Type                fType;
707     UnicodeString       fBogus; // Bogus string when it's needed.
708 };
709 
getDate(UErrorCode & status)710 inline UDate Formattable::getDate(UErrorCode& status) const {
711     if (fType != kDate) {
712         if (U_SUCCESS(status)) {
713             status = U_INVALID_FORMAT_ERROR;
714         }
715         return 0;
716     }
717     return fValue.fDate;
718 }
719 
getString(void)720 inline const UnicodeString& Formattable::getString(void) const {
721     return *fValue.fString;
722 }
723 
getString(void)724 inline UnicodeString& Formattable::getString(void) {
725     return *fValue.fString;
726 }
727 
728 #ifndef U_HIDE_DEPRECATED_API
getLong(UErrorCode * status)729 inline int32_t Formattable::getLong(UErrorCode* status) const {
730     return getLong(*status);
731 }
732 #endif  /* U_HIDE_DEPRECATED_API */
733 
toUFormattable()734 inline UFormattable* Formattable::toUFormattable() {
735   return reinterpret_cast<UFormattable*>(this);
736 }
737 
toUFormattable()738 inline const UFormattable* Formattable::toUFormattable() const {
739   return reinterpret_cast<const UFormattable*>(this);
740 }
741 
fromUFormattable(UFormattable * fmt)742 inline Formattable* Formattable::fromUFormattable(UFormattable *fmt) {
743   return reinterpret_cast<Formattable *>(fmt);
744 }
745 
fromUFormattable(const UFormattable * fmt)746 inline const Formattable* Formattable::fromUFormattable(const UFormattable *fmt) {
747   return reinterpret_cast<const Formattable *>(fmt);
748 }
749 
750 U_NAMESPACE_END
751 
752 #endif /* #if !UCONFIG_NO_FORMATTING */
753 
754 #endif //_FMTABLE
755 //eof
756