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