//********************************************************************************
//* File       : gString.hpp                                                     *
//* Author     : Mahlon R. Smith                                                 *
//*              Copyright (c) 2011-2026 Mahlon R. Smith, The Software Samurai   *
//*                 GNU GPL copyright notice below                               *
//* Date       : 20-Mar-2025                                                     *
//* Version    : (see gStringVersion string in gString.cpp)                      *
//*                                                                              *
//* Description: This class is used to convert between UTF-8 character           *
//* encoding and wchar_t character encoding. Statistical information for         *
//* analysis and display of the data is generated.                               *
//*                                                                              *
//*                                                                              *
//* Copyright Notice:                                                            *
//* -----------------                                                            *
//* This program is free software: you can redistribute it and/or modify it      *
//* under the terms of the GNU General Public License as published by the Free   *
//* Software Foundation, either version 3 of the License, or (at your option)    *
//* any later version, PROVIDED THAT the copyright notices for both code and     *
//* documentation are included and unmodified.                                   *
//*                                                                              *
//* This program is distributed in the hope that it will be useful, but          *
//* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY   *
//* or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License     *
//* for more details.                                                            *
//*                                                                              *
//* You should have received a copy of the GNU General Public License along      *
//* with this program.  If not, see <http://www.gnu.org/licenses/>.              *
//*                                                                              *
//*         Full text of the GPL License may be found in the Texinfo             *
//*         documentation for this program under 'Copyright Notice'.             *
//********************************************************************************

#ifndef GSTRING_INCLUDED
#define GSTRING_INCLUDED

//* _XOPEN_SOURCE must be defined for including cwchar header file *
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE
#endif   // _XOPEN_SOURCE

//*****************
//* Include Files *
//*****************
#include <cstdlib>      //* Misc. functionality including character conversion
#include <cstdint>      //* [u]int*_t definitions (C++13)
#include <cstdarg>      //* Variadic-function macro definitions
#include <cwchar>       //* For wcwidth function
#include <iostream>     //* For insertion operator only

//** For Debugging Only - Disable In Production.      **
//** Allows debug info to be reported to application. **
//** Refer to the 'gsmeter' test program.             **
#define DEBUG_GSTRING (0)

//* Storage Capacity:                                       *
//* 1) Minimum allocation is gsALLOCMIN.                    *
//*    This is 1024 32-bit characters.                      *
//*    a) This is also the default storage allocation:      *
//*                      gsALLOCDFLT.                       *
//*    b) Under most conditions, the capacity will be       *
//*       automatically increased if the size of the data   *
//*       exceeds the current buffer size.                  *
//* 2) The "medium" allocation == four(4) times the minimum.*
//*    1024 * 4 == 4096 32-bit characters (plus padding).   *
//* 3) Maximum allocation == one thousand times the minimum *
//*    which is 1024 * 1000 == 1,024,000 32-bit characters  *
//*    (plus padding).                                      *
//* ------------------------------------------------------- *
//* -- In Unicode there are a maximum of six(6) bytes per   *
//*    character; however, in practice, there are never     *
//*    more than four(4) bytes per character.               *
//*    Therefore, the UTF-8 (byte) buffer contains four     *
//*    times the elements of the character buffer; that is, *
//*    it uses the same amount of physical memory as the    *
//*    character buffer.                                    *
//* -- The character-width (column count) buffer is an array*
//*    of 16-bit integers -- one for each character.        *
//*    Note that this buffer _could have been_ implemented  *
//*    as a byte buffer; however, the hardware processes    *
//*    16-bit values faster than it handles bytes, so for   *
//*    this buffer, we chose speed over size.               *
const int32_t gsALLOCMIN = (1025) ;
const int32_t gsALLOCMED = (gsALLOCMIN - 1) * 4 + 1 ;
const int32_t gsALLOCMAX = (gsALLOCMIN - 1) * 1000 + 1 ;
const int32_t gsALLOCDFLT = gsALLOCMIN ;
const int32_t gsDFLTBYTES = gsALLOCMED ;

//* Max field-width parameter for the formatInt methods *
const short FI_MAX_4BYTE_WIDTH = 13 ;  // four-byte integer with comma separators
const short FI_MAX_8BYTE_WIDTH = 18 ;  // eight-byte integer with comma separators
const short FI_MAX_FIELDWIDTH = FI_MAX_8BYTE_WIDTH ;

//* For the 'formatInt' methods, the format of the units suffix.               *
//*     METRIC                       BINARY                                    *
//*     kilobytes (x/1000)           kibibytes (x/1024),                       *
//*     megabytes (x/1000000)        mibibytes (x/1024000)                     *
//*     gigabytes (x/1000000000)     gibibytes (x/1024000000).                 *
//*     terabytes (x/1000000000000)  tebibytes (x/1024000000000)               *
//* The 'formatInt' methods use metric (powers of 10) calculations by default. *
//*                                                                            *
//* The IEC (International System of Quantities) recommends lower-case for     *
//* metric (powers of 10) and upper-case for binary (powers of 2).             *
//* However, unless you must be accurate in presenting the data according to   *
//* IEC standard, it is recommended that you choose the format according to:   *
//* your space requirements, visual appeal, and clear communication with your  *
//* users.                                                                     *
enum fiUnits : short
{
   fiK,     // (default) single, upper-case character:   'K'   'M'   'G'   'T'
   fik,     // single, lower-case character          :   'k'   'm'   'g'   't'
   fiKb,    // two-character, Uppercase/Lowercase    :  'Kb'  'Mb'  'Gb'  'Tb'
   fikB,    // "official" metric 'kilo' designation  :  'kB'  'mB'  'gB'  'tB'
   fiKiB,   // "official" binary 'kibi' designation  : 'KiB' 'MiB' 'GiB' 'TiB'
} ;

//* Use the gsForm class with the gString constructor or operator= to create   *
//* a formatted string.                                                        *
//* Example:                                                                   *
//* char utfString[] = { "Hello! " } ;   short sVal = 21 ;   int iVal = 523 ;  *
//* gsForm gsf { L"%s: %hd %d", { utfString, &sVal, &iVal } } ;                *
//*    gString gs ;                                                            *
//*    gs = gsf ;                                                              *
//*       OR                                                                   *
//*    gString gs( gsf ) ;                                                     *
//* See also the description of the compose() method below.                    *
const short gsFormMAXARGS = 24 ;    // Maximum number of conversion parameters
class gsForm
{
   public:
   //* Formatting string that specifies data type and format for each of       *
   //* the parameters in argList.                                              *
   const wchar_t* fmtSpec ;

   //* Pointers to each value to be converted                                  *
   const void*    argList[gsFormMAXARGS] ;

} ;


//******************************
//** Define the gString class **
//******************************
class gString
{
public:
//* Destructor. Return all resources to the system.                              *
//* Input  : none                                                                *
//* Returns: nothing                                                             *
virtual ~gString() ;

//********************************************************************************
//**:G:                     Constructor Group                                   **
//********************************************************************************

//* Default Constructor:                                                         *
//* Initialize members using default gsALLOCDFLT  storage capacity.              *
//*                                                                              *
//* Input  : none                                                                *
//*                                                                              *
//* Returns: nothing                                                             *
gString ( void ) ;

//* Constructor: Initialize members using specified storage capacity.            *
//*                                                                              *
//* Input  : charAlloc: storage capacity                                         *
//*             interpreted as the maximum number of wchar_t (32-bit) characters *
//*             for the storage buffer.                                          *
//*             Range: gsALLOCMIN <= charAlloc <= gsALLOCMAX                     *
//*             -- The minimum allocation of gsALLOCDMIN will result in the      *
//*                same storage capacity at the parent gString class.            *
//*             -- The maximum allocation of gsALLOCMAX is 1000 times the        *
//*                minimum allocation.                                           *
//*             The specified value is normalized by rounding upward to the      *
//*             nearest multiple of gsALLOCMIN.                                  *
//*                                                                              *
//* Returns: nothing                                                             *
gString ( int32_t charAlloc ) ;

//* Constructor: Convert specified UTF-8-encoded source to gString.              *
//*                                                                              *
//* Input  : usrc     : pointer to a UTF-8-encoded, null-terminated string       *
//*          charLimit: (optional, -1 by default) maximum number of source       *
//*                     characters to be stored (not including nullchar).        *
//*                     This is the number of characters (NOT the number of      *
//*                     UTF-8 bytes).                                            *
//*                     If not specified, then all source data will be stored    *
//*                     up to the maximum storage limit.                         *
//*                                                                              *
//* Returns: nothing                                                             *
gString ( const char*    usrc, int32_t charLimit = -1 ) ;
gString ( const uint8_t* usrc, int32_t charLimit = -1 ) ;

//* Constructor: Convert specified wchar_t (UTF-32 encoded) source to gString.   *
//*                                                                              *
//* Input  : wsrc     : pointer to a wchar_t-encoded, null-terminated string     *
//*          charLimit: (optional, -1 by default) maximum number of source       *
//*                     characters to be stored (not including nullchar).        *
//*                     If not specified, then all source data will be stored    *
//*                     up to the maximum storage limit.                         *
//*                                                                              *
//* Returns: nothing                                                             *
gString ( const wchar_t* wsrc, int32_t charLimit = -1 ) ;

//* Constructor: Copy specified source object.                                   *
//*                                                                              *
//* Input  : bsrc : (by reference) object containing source data.                *
//*                                                                              *
//* Returns: nothing                                                             *
gString ( const gString& bsrc ) ;

//* Constructor: Convert formatting specification and its arguments to gString.  *
//*              Please refer to compose() method for more information.          *
//*              Important Note: The storage capacity for this constructor is    *
//*              fixed at gsALLOCDFLT, but will be automatically expanded        *
//*              if necessary to accomodate the formatted data.                  *
//*                                                                              *
//* Input  : fmt  : a format specification string in the style of sprintf(),     *
//*                 swprintf() and related formatting C/C++ functions.           *
//*          arg1 : pointer to first value to be converted according to 'fmt'    *
//*          ...  : optional arguments (between ZERO and gsfMAXARGS - 1)         *
//*                 Each optional argument is a POINTER (address of) the value   *
//*                 to be formatted.                                             *
//*                                                                              *
//* Returns: nothing                                                             *
gString ( const char* fmt, const void* arg1, ... ) 
          __attribute__ ((format (gnu_printf, 2, 0))) ;

//* Constructor: Convert specified integer value to gString.                     *
//*              Please see the 'formatInt' method for formatting details.       *
//*              Important Note: The storage capacity for this group of          *
//*              constructors is fixed at gsALLOCDFLT.                           *
//*                                                                              *
//* Input  : iVal  : integer value to be converted                               *
//*                  Supported value range: plus/minus 9.999999999999 terabytes  *
//*          fWidth: field width (number of display columns)                     *
//*                  range: 1 to FI_MAX_FIELDWIDTH                               *
//*          lJust : (optional, false by default)                                *
//*                  if true, strip leading spaces to left-justify the value     *
//*                  in the field. (resulting string may be less than fWidth)    *
//*          sign  : (optional, false by default)                                *
//*                  'false' : only negative values are signed                   *
//*                  'true'  : always prepend a '+' or '-' sign.                 *
//*          kibi  : (optional, false by default)                                *
//*                  'false' : calculate as a decimal value (powers of 10)       *
//*                            kilobyte, megabyte, gigabyte, terabyte            *
//*                  'true'  : calculate as a binary value (powers of 2)         *
//*                            kibibyte, mebibyte, gibibyte, tebibyte            *
//*          units : (optional) member of enum fiUnits (fiK by default)          *
//*                  specifies the format for the units suffix.                  *
//*                  Note that if the uncompressed value fits in the field,      *
//*                  then this parameter is ignored.                             *
//*                                                                              *
//* Returns: nothing                                                             *
//*          Note: if field overflow, field will be filled with '#' characters.  *
gString ( short iVal, short fWidth, bool lJust = false, 
          bool sign = false, bool kibi = false, fiUnits units = fiK ) ;
gString ( unsigned short iVal, short fWidth, bool lJust = false, 
          bool sign = false, bool kibi = false, fiUnits units = fiK ) ;
gString ( int iVal, short fWidth, bool lJust = false, 
          bool sign = false, bool kibi = false, fiUnits units = fiK ) ;
gString ( unsigned int iVal, short fWidth, bool lJust = false, 
          bool sign = false, bool kibi = false, fiUnits units = fiK ) ;
gString ( long iVal, short fWidth, bool lJust = false, 
          bool sign = false, bool kibi = false, fiUnits units = fiK ) ;
gString ( unsigned long iVal, short fWidth, bool lJust = false, 
          bool sign = false, bool kibi = false, fiUnits units = fiK ) ;
gString ( long long iVal, short fWidth, bool lJust = false, 
          bool sign = false, bool kibi = false, fiUnits units = fiK ) ;
gString ( unsigned long long iVal, short fWidth, bool lJust = false, 
          bool sign = false, bool kibi = false, fiUnits units = fiK ) ;


//********************************************************************************
//**:G:                    Initialization Group                                 **
//********************************************************************************

//* Create formatted text data from a format specification string including      *
//* between ZERO and gsfMAXARGS format specifications and their corresponding    *
//* argument pointers..                                                          *
//*                                                                              *
//* Supported data types:                                                        *
//*  %d, %i  integer (decimal)                                                   *
//*  %o      integer (octal)                                                     *
//*  %u      integer (unsigned)                                                  *
//*  %x, %X  integer (hex lower or upper case)                                   *
//*  %f      floating point (fixed point)                                        *
//*  %e, %E  floating point (scientific notation, lower/uppercase)               *
//*  %g, %G  floating point (normal/exponential, lower/uppercase)                *
//*  %a, %A  floating point (hex fraction)                                       *
//*  %c      character                                                           *
//*  %C      character (alias for %lc)                                           *
//*  %s      string                                                              *
//*  %S      string (alias for %ls)                                              *
//*  %p      pointer                                                             *
//*  %b, %B  (extension to swprintf - see description below)                     *
//*  %m      capture 'errno' description string (see /usr/include/errno.h)       *
//*  %n      number of characters printed so far                                 *
//*          (value written to corresponding argument's location)                *
//*  %%      literal '%'                                                         *
//*                                                                              *
//* See man pages for the C/C++ function 'swprintf' or                           *
//* 'Table of Output Conversions' for additional details.                        *
//* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  *
//*                                                                              *
//* Input  : fmt  : a format specification string in the style of sprintf(),     *
//*                 swprintf() and related formatting C/C++ functions.           *
//*          ...  : optional arguments (between ZERO and gsfMAXARGS)             *
//*                 Each optional argument is a POINTER (address of) the value   *
//*                 to be formatted.                                             *
//*                 - Important Note: There must be AT LEAST as many optional    *
//*                   arguments as the number of format specifiers defined in    *
//*                   the formatting string. Excess arguments will be ignored;   *
//*                   HOWEVER, too few arguments will result in an application   *
//*                   crash and ridicule from your peers.                        *
//*                                                                              *
//* Returns: const wchar_t* to formatted data                                    *
//*                                                                              *
//* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  *
//* Implementation Notes:                                                        *
//* =====================                                                        *
//*                                                                              *
//* 1) Unsupported data types                                                    *
//*    ======================                                                    *
//*    Conversion modifiers that are not fully supported at this time:           *
//*                       'j', 'z', 't', '%['                                    *
//*    Note: The '*' field-width specification or precision specification        *
//*          which uses the following argument as the width/precision value      *
//*          IS NOT supported.                                                   *
//*                                                                              *
//* 2) Binary-format specifier                                                   *
//*    =======================                                                   *
//*    We implement an extension to the swprintf output-conversion-specifiers    *
//*    for binary formatted output. We have found this formatting option useful  *
//*    when working with bit masks and for verifying bit-shifting operations.    *
//*    - Base formatting specifier:                                              *
//*       %b , %B                                                                *
//*    - Format modifiers for DATA SIZE are the same as for swprintf:            *
//*       hh , h , l , ll , L , q                                                *
//*    - Format modifier for prepending of a type indicator.                     *
//*       '#' (hash character)                                                   *
//*       This is the same principle as for prepending a '0x' indicator to hex   *
//*       output, and will place either a 'b' or 'B' character at the beginning  *
//*       of the output. Examples:  %#hhb -> b0101.1010   %#hhB -> B0101.1010    *
//*    - Format modifier for appending of a type indicator.                      *
//*       '-#' (minus sign and hash character)                                   *
//*       Rather than prepending the indicator, the indicator will be append     *
//*       to the end of the output.                                              *
//*       Examples: %-#hhb -> 0101.1010b   %-#hhB -> 0101.1010B                  *
//*    - Format modifier for specifying the group-seperator character.           *
//*       By default, the bit groups are seperated by a '.' (fullstop)           *
//*       character. To specify an alternate seperator character:                *
//*       % hB -> 0111 0101 1010 0001    (' ' (space) character as seperator)    *
//*       %_hB -> 0111_0101_1010_0001    ('_' (underscore) char as seperator)    *
//*       %#/hB -> B0111/0101/1010/0001  ('/' (slash) character as seperator)    *
//*       %-#-hB -> 0111-0101-1010-0001B ('-' (dash) character as seperator)     *
//*       Valid seperator characters are any printable ASCII character           *
//*       that IS NOT alphabetical, IS NOT a number, and IS NOT a '.'(fullstop)  *
//*    - Format modifier for specifying bit grouping.                            *
//*       By default, bits are formatted in groups of four (4 nybble); however,  *
//*       if desired, bits can be formatted in groups of eight (8 byte):         *
//*       %.8hB -> 01110101.10100001                                             *
//*       %-.8hB -> 01110101-10100001                                            *
//*       %# .8hB -> B01110101 10100001                                          *
//*       %-#`.8hb -> 01110101`10100001b                                         *
//*                                                                              *
//* 3) Format-specification Deficiencies                                         *
//*    =================================                                         *
//*    The compiler will scan your UTF-8 formatting string for valid             *
//*    formatting specifications and warn you of potential problems.             *
//*      HOWEVER:                                                                *
//*    The ANSI-C/C++ specification does not yet support parsing of wchar_t      *
//*    (swprintf-style) formatting strings. If you pass a wchar_t formatting     *
//*    string, the compiler will not be able to warn of potential problems,      *
//*    so construct your formatting string carefully. See gcc documentation      *
//*    for more information:  info -f gcc.info -n 'Function Attributes'          *
//*      ADDITIONALLY:                                                           *
//*    Because the optional parameters are passed as POINTERS, similar to the    *
//*    C/C++ library function 'sscanf' and friends, the compiler cannot perform  *
//*    automatic promotions from short int* to int* or from float* to double*,   *
//*    and so-on. For this reason, please use care that the data type you        *
//*    specify in the formatting string matches the data type of the variable    *
//*    referenced by its parameter pointer. For example, the conversion          *
//*    specifications:  %d, %i, %u, %x, and %X  assume a parameter of 'int'      *
//*    size If your actual variable declaration is for a 8-bit int, short int,   *
//*    long int or long long int, then explicitly indicate this in the           *
//*    corresponding conversion specification.                                   *
//*    Examples:                                                                 *
//*      char      Greeting[] = { "Hello!" } ;                                   *
//*      int       iValue ;                                                      *
//*      long long int qValue ;                                                  *
//*      long int  lValue ;                                                      *
//*      short int sValue1, sValue2, sValue3 ;                                   *
//*      bool      flagValue ;                                                   *
//*      float     fltValue ;                                                    *
//*      double    dblValue ;                                                    *
//*      gString gs ;                                                            *
//*      gs.compose( "%s - %d %12hd, %-hi, %#hx %08lX %llu %hhd",                *
//*                  Greeting, &iValue, &sValue1, &sValue2, &sValue3,            *
//*                  &lValue, &qValue, &flagValue );                             *
//*      gs.compose( "floating downstream:%10.2f and doubling our pace:%.4lf",   *
//*                  &fltValue, &dblValue ) ;                                    *
//*                                                                              *
//*      Note: Use care when formatting an 8-bit integer: 'char' ,               *
//*            'unsigned char' or a boolean value declared with the 'bool'       *
//*            keyword. For these types, use the 'hh' conversion modifier.       *
//*            Examples: %hhd , %hhu , %hhX                                      *
//*                                                                              *
//* 4) 'swprintf' bug-fix                                                        *
//*    ==================                                                        *
//*    The standard library 'swprintf' function has a design flaw for format     *
//*    specifications that include a field-width specifier.                      *
//*    'swprintf' pads the string to the specified number of CHARACTERS, not     *
//*    the number of COLUMNS as it should do. For (Arabic) numeric source        *
//*    values this is not a problem because one character == one display         *
//*    column. For string source data, however, if the source string contains    *
//*    characters that require more than one display column each, then the       *
//*    output may be too wide.                                                   *
//*    Therefore, for string-source-formatting specifications ONLY               *
//*          (examples: "%12s"  "%-6s"  "%16ls"  "%5S"  "%-24S")                 *
//*    we compensate for this anomalous behavior by interpreting the             *
//*    field-width specifier as number-of-columns, NOT number-of-characters.     *
//*    This will result in output that appears different (and better) than       *
//*    output created directly by the 'swprintf' function.                       *
//*                                                                              *
//* 5) Parameter type checking                                                   *
//*    =======================                                                   *
//*    Unfortunately, type-checking of wchar_t formatting strings is not yet     *
//*    supported by the gnu (v:4.8.0) compiler, (but see wchar.h which is        *
//*    preparing for future expansion). Thus, use care when constructing your    *
//*    'wchar_t fmt' formatting string. The 'char fmt' string is type-checked.   *
//* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  *
const wchar_t* compose ( const wchar_t* fmt, ... ) 
                         /*__attribute__ ((format (gnu_wprintf, 2, 0)))*/ ;
const wchar_t* compose ( const char* fmt, ... ) 
                         __attribute__ ((format (gnu_printf, 2, 0))) ;

//* Convert an integer value into a formatted display string of the specified    *
//* width. Value is right-justified in the field, with leading spaces added      *
//* if necessary (but see 'lJust' parameter).                                    *
//* Maximum field width is FI_MAX_FIELDWIDTH. This is wide enough to display     *
//* a 13-digit, signed and comma-formatted value: '+9,876,543,210,777'           *
//*                                                                              *
//* Actual formatting of the value depends on the combination of:                *
//*   a) magnitude of the value                                                  *
//*   b) whether it is a signed value                                            *
//*   c) the specified field-width                                               *
//*   d) the specified suffix format                                             *
//*   e) locale-specific grouping of digits according the LC_NUMERIC locale      *
//*      environment variable                                                    *
//* Examples are for the 'C' and U.S. English locale with default suffix.        *
//* 1) Simple comma formatted output if specified field-width is sufficient.     *
//*    Examples:  345    654,345    782,654,345    4,294,967,295                 *
//* 2) Compression of the value to fit a specified field width.                  *
//*    Examples:  12.3K    999K    12.345M    1.234G    4.3G                     *
//* Please see test application, 'bsmeter', for more examples.                   *
//*                                                                              *
//* Input  : iVal  : integer value to be converted                               *
//*                  Supported value range: plus/minus 9.999999999999 terabytes  *
//*          fWidth: field width (number of display columns)                     *
//*                  range: 1 to FI_MAX_FIELDWIDTH                               *
//*          lJust : (optional, false by default)                                *
//*                  if true, strip leading spaces to left-justify the value     *
//*                  in the field. (resulting string may be less than fWidth)    *
//*          sign  : (optional, false by default)                                *
//*                  'false' : only negative values are signed                   *
//*                  'true'  : always prepend a '+' or '-' sign.                 *
//*          kibi  : (optional, false by default)                                *
//*                  'false' : calculate as a decimal value (powers of 10)       *
//*                            kilobyte, megabyte, gigabyte, terabyte            *
//*                  'true'  : calculate as a binary value (powers of 2)         *
//*                            kibibyte, mebibyte, gibibyte, tebibyte            *
//*         units  : (optional) member of enum fiUnits (fiK by default)          *
//*                  specifies the format for the units suffix.                  *
//*                  Note that if the uncompressed value fits in the field,      *
//*                  then this parameter is ignored.                             *
//*                                                                              *
//* Returns: 'true' if successful                                                *
//*          'false' if field overflow (field will be filled with '#' chars)     *
//*                  note that oveflow can occur ONLY:                           *
//*                  if fWidth <= 3 OR                                           *
//*                  if iVal <= -10.0 terabytes OR iVal >= 10.0 terabytes        *
//*                  if units is a multi-column substring, then some values      *
//*                     will overflow 4-column, 5-column, and 6-column fields    *
bool  formatInt ( short iVal, short fWidth, bool lJust = false, 
                  bool sign = false, bool kibi = false, fiUnits units = fiK ) ;
bool  formatInt ( unsigned short iVal, short fWidth, bool lJust = false, 
                  bool sign = false, bool kibi = false, fiUnits units = fiK ) ;
bool  formatInt ( int iVal, short fWidth, bool lJust = false, 
                  bool sign = false, bool kibi = false, fiUnits units = fiK ) ;
bool  formatInt ( unsigned int iVal, short fWidth, bool lJust = false, 
                  bool sign = false, bool kibi = false, fiUnits units = fiK ) ;
bool  formatInt ( long iVal, short fWidth, bool lJust = false,
                  bool sign = false, bool kibi = false, fiUnits units = fiK ) ;
bool  formatInt ( unsigned long iVal, short fWidth, bool lJust = false, 
                  bool sign = false, bool kibi = false, fiUnits units = fiK ) ;
bool  formatInt ( long long iVal, short fWidth, bool lJust = false, 
                  bool sign = false, bool kibi = false, fiUnits units = fiK ) ;
bool  formatInt ( unsigned long long iVal, short fWidth, bool lJust = false, 
                  bool sign = false, bool kibi = false, fiUnits units = fiK ) ;

//* Assignment operator: converts UTF-8-encoded source to gString.               *
void operator= ( const char* usrc ) ;
void operator= ( const uint8_t* usrc ) ;

//* Assignment operator: converts wchar_t ('wide') source to gString.            *
void operator= ( const wchar_t* wsrc ) ;

//* Assignment operator: Copies one gString object to another.                   *
void operator= ( const gString& bssrc ) ;

//* Load the specified number of characters from the source data.                *
//* By default, the new text REPLACES the existing text; however, the 'append'   *
//* parameter allows the new text to be appended to the existing text.           *
//* Combined character count is limited to maximum storage capacity.             *
//*                                                                              *
//* Input  : usrc     : pointer to a UTF-8 encoded string (char* or uint8_t*)    *
//*                     OR                                                       *
//*          wsrc     : pointer to a UTF-32 (wchar_t) encoded string             *
//*          charLimit: maximum number of characters (not bytes) from source     *
//*                     array to load. Range: 1 through target storage capacity  *
//*                     The count should not include the NULL terminator         *
//*          append   : (optional, 'false' by default)                           *
//*                     if 'false', replace existing text with specified text    *
//*                     if 'true', append new text to existing text              *
//*                                                                              *
//* Returns: number of characters in modified string (incl. NULL terminator)     *
int32_t loadChars ( const wchar_t* wsrc, int32_t charLimit, bool append = false ) ;
int32_t loadChars ( const char* usrc, int32_t charLimit, bool append = false ) ;
int32_t loadChars ( const uint8_t* usrc, int32_t charLimit, bool append = false ) ;


//********************************************************************************
//**:G:                     Statistics Group                                    **
//********************************************************************************

//* Return a const pointer to the array of wchar_t (wide) characters.            *
//*                                                                              *
//* Input  : none                                                                *
//* Returns: pointer to array of wchar_t characters                              *
const wchar_t* gstr ( void ) const ;

//* Return a const pointer to the array of wchar_t (wide) characters.            *
//*                                                                              *
//* Input  : charCount : (by reference, initial value ignored)                   *
//*                      receives number of characters in array,                 *
//*                      including null terminator                               *
//* Returns: pointer to array of wchar_t characters                              *
const wchar_t* gstr ( int32_t& charCount ) const ;

//* Return a const pointer to the array of UTF-8-encoded char characters.        *
//*                                                                              *
//* Input  : none                                                                *
//* Returns: pointer to array of const char characters                           *
const char* ustr ( void ) const ;

//* Return a const pointer to the array of UTF-8-encoded char characters.        *
//*                                                                              *
//* Input  : charCount:(by reference, initial value ignored)                     *
//*          receives number of characters in array, including null terminator   *
//*        : byteCount:(by reference, initial value ignored)                     *
//*          receives number of data bytes in array                              *
//* Returns: pointer to array of const char characters                           *
const char* ustr ( int32_t& charCount, int32_t& byteCount ) const ;

//* Returns the number of characters in the string including null terminator     *
int32_t gschars ( void ) const ;

//* Returns the number of columns required to display the string.                *
int32_t gscols ( void ) const ;

//* Returns a pointer to an array of column counts, one for each character       *
//* of the text data. charCount gets number of characters in display string.     *
const short* gscols ( int32_t& charCount ) const ;

//* Returns the number of bytes in the UTF-8-encoded string (incl. null)         *
int32_t utfbytes ( void ) const ;

//* Returns 'true' if data are pure 7-bit ASCII, 'false' otherwise.              *
bool  isASCII ( void ) ;

//* Report data storage allocation for the gString object:                       *
//* Note that this the maximum UTF-32 (wchar_t) characters (or UTF-8 byte)       *
//* capacity, NOT the current number of characters or bytes stored.              *
//*   wAlloc : returns the storage allocation for UTF-32 (wchar_t) characters    *
//*   uAlloc : returns the storage allocation for UTF-8 bytes                    *
//*                                                                              *
//* Input  : none                                                                *
//* Returns: size of dynamic storage allocation in wchar_t words                 *
//*          OR                                                                  *
//*          size of dynamic storage allocation in uint8_t (char) bytes          *
//*         (overflow padding is not included in the reported count)             *
int32_t wAlloc ( void ) const ;
int32_t uAlloc ( void ) const ;

//* Reports the amount of free buffer space available, expressed as a count of   *
//* UTF-32 (wchar_t) characters.                                                 *
//*                                                                              *
//* Input  : none                                                                *
//*                                                                              *
//* Returns: available buffer space                                              *
//*          Note: If zero(0) is returned, data may have been truncated to fit.  *
int32_t freeSpace ( void ) const ;

//* Returns a pointer to version number string for the gString class.            *
const char* Get_gString_Version ( void ) const ;


//********************************************************************************
//**:G:                   Data Modification Group                               **
//********************************************************************************

//* Append text to existing gString text data.                                   *
//* Please BE CERTAIN that the source data are null terminated.                  *
//*                                                                              *
//* Input  : wPtr: pointer to array of wchar_t 'wide' text to be appended        *
//*           OR                                                                 *
//*          uPtr: pointer to array of char UTF-8 text to be appended            *
//*           OR                                                                 *
//*          wChar: a single, 'wide' character                                   *
//* Returns: number of characters in resulting string (incl. NULL terminator)    *
//*          Note: If the operation exceeds storage capacity, excess data        *
//*                will be truncated.                                            *
int32_t append ( const wchar_t* wPtr ) ;
int32_t append ( const char* uPtr ) ;
int32_t append ( const uint8_t* uPtr ) ;
int32_t append ( const wchar_t wChar ) ;

//* Append formatted text data to existing gString text data.                    *
//*                                                                              *
//* Please refer to compose() method for more information on converting data     *
//* using a format-specification string.                                         *
//*                                                                              *
//* Input  : fmt  : a format specification string in the style of sprintf(),     *
//*                 swprintf() and related formatting C/C++ functions.           *
//*          arg1 : pointer to first value to be converted by 'fmt'              *
//*          ...  : optional arguments (between ZERO and gsfMAXARGS - 1)         *
//*                 Each optional argument is a POINTER (address of) the value   *
//*                 to be formatted.                                             *
//*                                                                              *
//* Returns: number of characters in resulting string (incl. NULL terminator)    *
//*          Note: If the operation exceeds storage capacity, excess data        *
//*                will be truncated.                                            *
int32_t append ( const char* fmt, const void* arg1, ... ) 
                 __attribute__ ((format (gnu_printf, 2, 0))) ;
int32_t append ( const wchar_t* fmt, const void* arg1, ... ) 
               /*__attribute__ ((format (gnu_wprintf, 2, 0)))*/ ;

//* Insert text into existing gString text data up to a combined length of       *
//* storage capacity.                                                            *
//*                                                                              *
//* Input  : wPtr  : pointer to array of wchar_t 'wide' text to be inserted      *
//*           OR                                                                 *
//*          uPtr  : pointer to array of char UTF-8 text to be inserted          *
//*           OR                                                                 *
//*          wChar : a single wchar_t 'wide' character                           *
//*          offset: (optional, ZERO by default)                                 *
//*                  character offset at which to insert specified text into     *
//*                  existing text.                                              *
//*                  Note: if specified 'offset' > number of characters in       *
//*                        existing text, then acts like 'append' method.        *
//* Returns: number of characters in resulting string (incl. NULL terminator)    *
//*          Note: If the operation exceeds storage capacity, excess data        *
//*                will be truncated.                                            *
int32_t insert ( const wchar_t* wPtr, int32_t offset = 0 ) ;
int32_t insert ( const char* uPtr, int32_t offset = 0 ) ;
int32_t insert ( const uint8_t* uPtr, int32_t offset = 0 ) ;
int32_t insert ( wchar_t wChar, int32_t offset = 0 ) ;

//* Insert formatted text data into existing text data at the specified offset.  *
//*                                                                              *
//* Please refer to compose() method for more information on converting data     *
//* using a format-specification string.                                         *
//*                                                                              *
//* Input  : offset: a format specification string in the style of sprintf(),    *
//*                  Set to zero(0) to insert data a head of buffer.             *
//*          fmt   : a format specification string in the style of sprintf(),    *
//*                  swprintf() and related formatting C/C++ functions.          *
//*                  Format spec may be either char data or wchar_t data.        *
//*          arg1  : pointer to first value to be converted by 'fmt'             *
//*          ...   : optional arguments (between ZERO and gsfMAXARGS - 1)        *
//*                  Each optional argument is a POINTER (address of) the value  *
//*                  to be formatted.                                            *
//*                                                                              *
//* Returns: number of characters in resulting string (incl. NULL terminator)    *
//*          Note: If the operation exceeds storage capacity, excess data        *
//*                will be truncated.                                            *
int32_t insert( int32_t offset, const wchar_t* fmt, const void* arg1, ... ) ;
int32_t insert( int32_t offset, const char* fmt, const void* arg1, ... ) ;

//* Scan the data for a matching substring, and if found, erase(delete) the      *
//* first occurance of the substring.                                            *
//*                                                                              *
//* Actual comparison is always performed against the 'wide' character array     *
//* using wcsncasecmp (or wcsncmp). Null terminator character IS NOT included    *
//* in the comparison. These comparisons are not locale dependent.               *
//*                                                                              *
//* Input  : src    : source data to be matched, one of the following:           *
//*                   -- pointer to a wchar_t string                             *
//*                   -- pointer to a UTF-8 string                               *
//*                   -- a gString object containing the source (by reference)   *
//*                   -- a single, wchar_t character                             *
//*          offset : (optional, ZERO by default)                                *
//*                   character index at which to begin search                   *
//*                   NOTE: This is a character index, NOT a byte offset.        *
//*          casesen: (optional, 'false' by default)                             *
//*                   if 'false', then scan IS NOT case sensitive                *
//*                   if 'true, then scan IS case sensitive                      *
//*          all    : (optional, 'false' by default)                             *
//*                   if 'false', then only the first instance of the substring  *
//*                               will be deleted                                *
//*                   if 'true',  then all instances of the specified substring  *
//*                               from 'offset' forward will be deleted          *
//*                                                                              *
//* Returns: index of first character following the deleted sequence             *
//*          Note: This is the wchar_t character index, NOT a byte index         *
//*          Returns (-1) if:                                                    *
//*            a) no matching substring found                                    *
//*            b) 'offset' out-of-range                                          *
//*            c) 'src' is an empty string or a NULL character                   *
int32_t erase ( const char* src, int32_t offset = 0, 
                bool casesen = false, bool all = false ) ;
int32_t erase ( const uint8_t* src, int32_t offset = 0, 
                bool casesen = false, bool all = false ) ;
int32_t erase ( const wchar_t* src, int32_t offset = 0, 
                bool casesen = false, bool all = false ) ;
int32_t erase ( const gString& src, int32_t offset = 0, 
                bool casesen = false, bool all = false ) ;
int32_t erase ( wchar_t src, int32_t offset = 0, 
                bool casesen = false, bool all = false ) ;

//* Erase (delete) the data sequence specified by 'offset' and 'length'.         *
//* 'offset' is the index of the first character to be deleted, and 'length'     *
//* specifies the number of characters to delete.                                *
//*   1) If the 'length' specifies deletion of more characters than remain,      *
//*      then the 'erase' method has the same effect as calling the              *
//*      'limitChars' method.                                                    *
//*   2) If the defaults for both 'offset' and length' are used, then the        *
//*      'erase' method has the same effect as calling the 'clear' method.       *
//*   3) Note that the NULL terminator will never be deleted.                    *
//*   4) If:  a) offset < ZERO,                                                  *
//*           b) offset >= number of characters,                                 *
//*           c) length <= ZERO                                                  *
//*      then data will not be modified and (-1) will be returned.               *
//*                                                                              *
//* Input  : offset : (optional, ZERO by default)                                *
//*                   index of first character of sequence to be erased          *
//*                   NOTE: This is a character index, NOT a byte offset.        *
//*          length : (optional, gsALLOCMAX by default)                          *
//*                   if not specified, then erase all characters from           *
//*                      'offset' to end of data                                 *
//*                   if specified, then erase the specified number of           *
//*                      characters beginning at 'offset'                        *
//* Returns: index of first character following the deleted sequence             *
//*          Note: This is the wchar_t character index, NOT a byte index         *
//*          Returns (-1) if parameter out-of-range (data not modified)          *
int32_t erase ( int32_t offset = 0, int32_t length = gsALLOCMAX ) ;

//* Replace the specified source substring with the provided substring.          *
//*                                                                              *
//* Actual comparison is always performed against the 'wide' character array     *
//* using wcsncasecmp (or wcsncmp). Null terminator character IS NOT included    *
//* in the comparison. These comparisons are not locale dependent.               *
//*                                                                              *
//* Input  : srctxt : source data to be matched, one of the following:           *
//*                   -- pointer to a UTF-8 string                               *
//*                   -- pointer to a wchar_t string                             *
//*                   -- a single, wchar_t character                             *
//*          newtxt : data to overwrite existing text, one of the following:     *
//*                   -- pointer to a UTF-8 string                               *
//*                   -- pointer to a wchar_t string                             *
//*                   -- a single, wchar_t character                             *
//*          offset : (optional, ZERO by default)                                *
//*                   character index at which to begin search                   *
//*                   NOTE: This is a character index, NOT a byte offset.        *
//*          casesen: (optional, 'false' by default)                             *
//*                   if 'false', then scan IS NOT case sensitive                *
//*                   if 'true, then scan IS case sensitive                      *
//*          all    : (optional, 'false' by default)                             *
//*                   if 'false', then replace only the first occurance found    *
//*                   if 'true',  then replace all occurances of the specified   *
//*                               substring                                      *
//* Returns: 'true' if successful                                                *
//*          returns 'false' if error (existing data not modified):              *
//*            a) no matching source substring found                             *
//*            b) 'src' is a empty string or a null character                    *
//*            c) offset < ZERO or offset is beyond existing data                *
//*            d) modifying the data would cause buffer overflow                 *
bool replace ( const wchar_t* srctxt, const wchar_t* newtxt, int32_t offset = 0, 
               bool casesen = false, bool all = false ) ;
bool replace ( const wchar_t* srctxt, const char* newtxt, int32_t offset = 0,
               bool casesen = false, bool all = false ) ;
bool replace ( const wchar_t* srctxt, const wchar_t newtxt, int32_t offset = 0,
               bool casesen = false, bool all = false ) ;
bool replace ( const char* srctxt, const wchar_t* newtxt, int32_t offset = 0,
               bool casesen = false, bool all = false ) ;
bool replace ( const char* srctxt, const char* newtxt, int32_t offset = 0,
               bool casesen = false, bool all = false ) ;
bool replace ( const char* srctxt, const wchar_t newtxt, int32_t offset = 0,
               bool casesen = false, bool all = false ) ;
bool replace ( const wchar_t srctxt, const wchar_t* newtxt, int32_t offset = 0,
               bool casesen = false, bool all = false ) ;
bool replace ( const wchar_t srctxt, const char* newtxt, int32_t offset = 0,
               bool casesen = false, bool all = false ) ;
bool replace ( const wchar_t srctxt, const wchar_t newtxt, int32_t offset = 0,
               bool casesen = false, bool all = false ) ;

//* Shift text data by the specified number of characters.                       *
//*                                                                              *
//* Input  : shiftCount: < ZERO: shift data to the left, discarding the          *
//*                              specified number of characters from the         *
//*                              beginning of the array                          *
//*                      > ZERO: shift data to the right, padding the vacated    *
//*                              positions on the left with 'padChar'            *
//*                      ==ZERO: do nothing                                      *
//*          padChar   : (optional, SPACE character, 0x20 by default)            *
//*                      when shifting data to the right, use this character     *
//*                      to fill the vacated character positions                 *
//* Returns: number of characters in adjusted array                              *
int32_t shiftChars ( int32_t shiftCount, wchar_t padChar = L' ' ) ;

//* Shift text data by the specified number of display columns.                  *
//*                                                                              *
//* Input  : shiftCount: < ZERO: shift data to the left, discarding the          *
//*                              number of characters equivalent to the          *
//*                              specified number of display columns             *
//*                              NOTE: May discard one extra column if count     *
//*                              falls within a multi-column character.          *
//*                      > ZERO: shift data to the right, padding the vacated    *
//*                              positions on the left with 'padChar'            *
//*                      ==ZERO: do nothing                                      *
//*          padChar   : (optional, SPACE character, 0x20 by default)            *
//*                      when shifting data to the right, use this character     *
//*                      to fill the vacated column positions                    *
//*                      NOTE: Specify a one-column character ONLY as the        *
//*                      padding character. (multi-column characters ignored)    *
//* Returns: number of columns in adjusted array                                 *
int32_t shiftCols ( int32_t shiftCount, wchar_t padChar = L' ' ) ;

//* Shift existing data to the right, so that the full width of the data is      *
//* equal to the specified number of columns.                                    *
//*                                                                              *
//* If the width of the existing data is greater-than-or-equal-to the specified  *
//* field width, then the data will not be modified.                             *
//*                                                                              *
//* Input  : fieldWidth: number of columns for the adjusted data array           *
//*          padChar   : (optional, SPACE character, 0x20 by default)            *
//*                      character with which to pad the data                    *
//*                      NOTE: Specify a one-column character ONLY as the        *
//*                      padding character. (multi-column characters ignored)    *
//* Returns: number of columns in adjusted array                                 *
int32_t rightJustify ( int32_t fieldWidth, wchar_t padChar = L' ' ) ;

//* Add padding to the end of the existing data to equal the specified number    *
//* of columns.                                                                  *
//*                                                                              *
//* If 'centered' flag is set, divide the padding equally between the beginning  *
//* and end of the data. Note that if an odd number of columns is to be added,   *
//* then the odd column will be placed at the end of the data.                   *
//*                                                                              *
//* a) Padding will be added until either the specified number of columns is     *
//*    reached, OR until the array contains the maximum number of characters     *
//*    (storage limit).                                                          *
//* b) If 'fieldWidth' <= current width, then data will not be modified.         *
//*                                                                              *
//* Input  : fieldWidth: number of columns for the adjusted data array           *
//*          padChar   : (optional, SPACE character, 0x20 by default)            *
//*                      character with which to pad the data                    *
//*                      NOTE: Specify a one-column character ONLY as the        *
//*                      padding character. (multi-column characters ignored)    *
//*          centered  : (optional, 'false' by default)                          *
//*                      if 'false', all padding will be appended at the end     *
//*                                  of the existing data                        *
//*                      if 'true',  padding will be equally divided between     *
//*                                  the beginning and end of the existing data  *
//* Returns: number of columns in adjusted array                                 *
int32_t padCols ( int32_t fieldWidth, wchar_t padChar = L' ', bool centered = false ) ;

//* Strip leading and/or trailing whitespace.                                    *
//* Recognizes both the ASCII space 0x20 and the CJK (two-column) space 0x3000   *
//* as well as TAB (0x09), VTAB (0x0B), Newline (0x0A), Carriage-return (0x0D),  *
//* and Form-feed (0x0C).                                                        *
//*                                                                              *
//* Input  : leading  : (optional, 'true' by default)                            *
//*                     If 'true',  remove whitespace from beginning of string.  *
//*                     If 'false', leading whitespace is unchanged.             *
//*          trailing : (optional, 'true' by default)                            *
//*                     If 'true',  remove whitespace from end of string.        *
//*                     If 'false', trailing whitespace is unchanged.            *
//* Returns: number of characters in modified string (incl. NULL terminator)     *
int32_t strip ( bool leading = true, bool trailing = true ) ;

//* Truncate the existing data to no more than charCount display characters.     *
//* Insert a null terminator after the specified number of characters            *
//*                                                                              *
//* Input  : maximum number of characters to be retained.                        *
//*          (not including NULL) Range: 1 to storage capacity: wAlloc() - 1     *
//* Returns: number of characters in tne adjusted data (including nullchar)      *
int32_t limitChars ( int32_t charCount ) ;

//* Truncate the existing data to no more than colCount display columns.         *
//* Insert a null terminator after the number of characters required to fill     *
//* the specified number of display columns.                                     *
//*                                                                              *
//* Note that some characters such as '\n' and '\0' have zero width.             *
//*                                                                              *
//* Input  : maximum number of display columns available for data display        *
//*          Range: 1 to storage capacity.                                       *
//* Returns: number of columns of display data retained                          *
int32_t limitCols ( int32_t colCount ) ;

//* Reverse the order of characters in the text string.                          *
//* If RTL text data displayed by your application is not formatted as desired,  *
//* then this method may be used to reverse the character order before writing   *
//* to the display. This is useful for manipulating both RTL (Right-To-Left)     *
//* language text and mixed RTL/LTR text.                                        *
//*   Example:  "?םיירהצ תחוראל ןכומ התא םאה"   (displayed here correctly)       *
//*   Becomes:  "האם אתה מוכן לארוחת צהריים?"   (inverted character sequence)    *
//*                                                                              *
//* Although modern web browsers (Firefox, Opera, Chromium, etc.) _usually_      *
//* handle RTL text correctly, other applications often do not.                  *
//* This is expecially true of terminal emulator software. GNOME Terminal and    *
//* KDE Konsole for instance, try to be "helpful" by automatically re-ordering   *
//* the text and/or moving terminating punctuation to the opposite end of the    *
//* string. Unfortunately these applications really do not understand what       *
//* they are doing. They recognize when text belongs to an RTL language, but     *
//* cannot understand whether it is in the proper order, which means that the    *
//* text _may be_ displayed incorrectly.                                         *
//*                                                                              *
//* Input  : punct : (optional, 'false' by default)                              *
//*                  if 'false', invert entire string                            *
//*                  if 'true' AND if a punctuation mark is seen at either end   *
//*                     of the string, invert everything except the punctuation  *
//*                     mark(s). typically one of the following:                 *
//*                     '.' ',' '?' '!' ';' ':' but see note.                    *
//*          para  : (optional, 'false' by default)                              *
//*                  if 'false', invert data as a single character stream        *
//*                  if 'true',  invert data separately for each logical line    *
//*                              (line data are separated by newlines ('\n')     *
//*          rjust : (optional, 'false' by default)                              *
//*                  if 'false', do not insert right-justification padding       *
//*                  if 'true',  insert padding for each logical line to         *
//*                              right-justify the data                          *
//*                              (used to right-justify LTR output)              *
//*                              Note that right-justification is performed      *
//*                              ONLY if the 'para' parameter is true.           *
//*                              Otherwise, 'rjust' will be ignored.             *
//*                                                                              *
//* Returns: number of wchar_t characters in gString object                      *
//*          (if return value >= gsALLOCMAX, data may have been truncated)       *
int32_t textReverse ( bool punct = false, bool para = false, bool rjust = false ) ;

//* Reformat the text so that when written to the display, it will fit within    *
//* the specified rectangular area.                                              *
//*                                                                              *
//*  1) Remove all newlines from the text.                                       *
//*  2) Perform word wrap to limit width of each row of the paragraph.           *
//*  3) If necessary, truncate the text to limit the height of the paragraph.    *
//*     (but see the 'trunc' and 'truncIndex' parameters)                        *
//*                                                                              *
//* Input  : maxRows  : maximum rows for message (>= 1)                          *
//*          maxCols  : maximum columns on any message row (>= 4)                *
//*          trunc    : (optional, 'true' by default)                            *
//*                     if 'true',  truncate the data if necessary to ensure     *
//*                                 that the data do not extend beyond the       *
//*                                 specified target area                        *
//*                     if 'false', format the entire source text array, even    *
//*                                 if doing so requires violating the specified *
//*                                 height of the target area (maxRows).         *
//*                                 (see also 'truncIndex' parameter)            *
//*          hyphenbrk: (optional, 'false' by default)                           *
//*                     if 'false', automatic line breaks occur at space ' '     *
//*                                 characters only.                             *
//*                                 Special Case: the following CJK ideographs   *
//*                                 are also recognized as whitespace            *
//*                                 (see documentation for details)              *
//*                                  '、' comma U+3001 and                        *
//*                                  '。' full stop U+3002                        *
//*                     if 'true',  in addition to the space ' ' characters,     *
//*                                 enable line break at:                        *
//*                                  ASCII hyphen    '-' (2dh)                   *
//*                                  Unicode &mdash; '—' (2014h)                 *
//*                                  Unicode &ndash; '–' (2013h)                 *
//*                                  Unicode &minus; '−' (2212h)                 *
//*                                  Unicode &shy;       (00ADh) (soft hyphen)   *
//*          truncIndex: (optional, null pointer by default)                     *
//*                      -- referenced _only_ when the 'trunc' flag is reset     *
//*                      if specified, points to a variable to receive the       *
//*                      index at which the data _would_have_been_ truncted to   *
//*                      fit the specified height of the target area if the      *
//*                      'trunc' flag had been set.                              *
//*                      a) A positive value indicates that the data have not    *
//*                         been truncated, AND that the data extend beyond      *
//*                         the specified target area.                           *
//*                      b) A negative value indicates that it was not necessary *
//*                         to truncate the data i.e. the data fit entirely      *
//*                         within the target area.                              *
//*                                                                              *
//* Returns: number of text rows in the formatted output                         *
int32_t formatParagraph ( int32_t maxRows, int32_t maxCols, bool trunc = true, 
                          bool hyphenbrk = false, int32_t *truncIndex = NULL ) ;

//* Reset contents to an empty string i.e. "". The data will consist of a        *
//* single, nullchar character ('\0'). The character and byte counts are         *
//* set to 1 (one), and the column count is zero.                                *
//*                                                                              *
//* Input  : none                                                                *
//* Returns: nothing                                                             *
void  clear ( void ) ;

//* Increase or decrease the size of storage buffer by the specified number      *
//* of gsALLOCMIN increments.                                                    *
//* The buffer is sized in multiples of gsALLOCMIN in the range:                 *
//*                 gsALLOCMIN <= size <= gsALLOCMAX                             *
//*                 1024 chars            1,024,000 chars                        *
//*                                                                              *
//* Input  : steps : number of steps to increase or decrease in buffer size.     *
//*                  Range: +/-999                                               *
//*                  If value out of range, will be set to upper/lower limit.    *
//*          clear : (optional, 'false' by default)                              *
//*                  if 'false', if possible, retain the existing contents       *
//*                              of the buffer. (Note that if buffer size is     *
//*                              reduced, some data may be truncated.)           *
//*                  if 'true',  erase any existing text in the buffer           *
//*                              (same as 'clear' method, above)                 *
//*                                                                              *
//* Returns: new buffer capacity expressed as the number of wchar_t characters   *
int32_t reAlloc ( int32_t steps, bool clear = false ) ;


//********************************************************************************
//**:G:                        Analysis Group                                   **
//********************************************************************************

//* Comparison operator: Compares the text content of two gString objects.       *
//* The comparison is performed against the objects' wchar_t character arrays,   *
//* and is case-sensitive.                                                       *
//*                                                                              *
//* Input  : (by reference) gString object to be compared                        *
//* Returns: 'true' if the strings are identical, else 'false'                   *
bool operator== ( const gString& bs2 ) const ;
//* Comparison operator: Compares the text content of two gString objects.       *
//* The comparison is performed against the objects' wchar_t character arrays,   *
//* and is case-sensitive.                                                       *
//*                                                                              *
//* Input  : (by reference) gString object to be compared                        *
//* Returns: 'true' if the strings differ, else 'false'                          *
bool operator!= ( const gString& bs2 ) const ;

//* Compares the text content of the gString object with the specified text.     *
//* The comparison is performed against the source and target wchar_t character  *
//* arrays. The relationship between upper-case and lower-case characters is     *
//* locale dependent.                                                            *
//*                                                                              *
//* Input  : uStr     : (UTF-8 string) to be compared                            *
//*             OR                                                               *
//*          wStr     : (wchar_t string) to be compared                          *
//*             OR                                                               *
//*          gs       : (gString object by reference) data to be compared        *
//*          casesen  : (optional, 'true' by default)                            *
//*                     if 'true' perform case-sensitive comparison              *
//*                     if 'false' perform case-insensitive comparison           *
//*          length   : (optional, -1 by default. i.e. compare to end)           *
//*                     maximum number of characters to compare                  *
//*                     (applies to 'uStr' and 'wStr' source parameters only)    *
//*          offset   : (optional, ZERO by default)                              *
//*                     If specified, equals the character offset into the       *
//*                     gString character array at which to begin comparison.    *
//*                     (applies to 'uStr' and 'wStr' source parameters only)    *
//*                                                                              *
//* Returns: using the rules of the 'wcsncmp' (or 'wcsncasecmp') library         *
//*          function (see string.h):                                            *
//*     ZERO, text data are identical                                            *
//*   > ZERO, first differing char of stored data is numerically larger.         *
//*   < ZERO, first differing char of stored data is numerically smaller.        *
int32_t compare ( const char* uStr, bool casesen = true, 
                  int32_t length = -1, int32_t offset = 0 ) const ;
int32_t compare ( const uint8_t* uStr, bool casesen = true, 
                  int32_t length = -1, int32_t offset = 0 ) const ;
int32_t compare ( const wchar_t* wStr, bool casesen = true, 
                  int32_t length = -1, int32_t offset = 0 ) const ;
int32_t compare ( const gString& gStr, bool casesen = true ) const ;

//* Compares the text content of the gString object with the specified text.     *
//* The comparison is performed according to the active "locale" within the      *
//* application. This comparison is known as the "collation order" or            *
//* "dictionary order" comparison where lowercase letters are considered as      *
//* less than their uppercase equivalents. Characters with diacritical markers   *
//* and unitary character sequences (e.g. Spanish 'll') will also be sorted      *
//* according to the rules of the active locale.                                 *
//*                                                                              *
//* a) If the application has set the locale, the rules of that locale will be   *
//*    used for the comparison.                                                  *
//* b) If the application has not specified the locale, then the so-called       *
//*    POSIX C/C++ pseudo-locale will be used.                                   *
//* c) Note that for some languages, Chinese and Japanese for instance, there    *
//*    is no "dictionary" order for the characters. Instead, dictionaries rely   *
//*    on sound markers, e.g. pinyin transliteration, stroke count, or other     *
//*    criteria. The 'compcoll' is not effective for these languages.            *
//* d) Note that if the source data contain mixed languages, the 'wcscoll'       *
//*    function will be ineffective and misleading.                              *
//* e) Technical Note: The 'wcscoll' librarary function is also _considerably_   *
//*    slower than the 'wcscmp' (numeric sort) function because it scans the     *
//*    data multiple times.                                                      *
//*                                                                              *
//* Note: Regardless of source data format, this method uses the C-library       *
//*       'wcscoll' function exclusively to perform the comparison.              *
//*                                                                              *
//* Input  : wStr     : (UTF-32 string) to be compared                           *
//*             OR                                                               *
//*          uStr     : (UTF-8 string) to be compared                            *
//*             OR                                                               *
//*          gs       : (gString object by reference) data to be compared        *
//*                                                                              *
//* Returns: using the rules of the 'wcscoll' library function (see wchar.h):    *
//*     ZERO, text data are identical                                            *
//*   > ZERO, first differing char of stored data is larger.                     *
//*   < ZERO, first differing char of stored data is smaller.                    *
int32_t compcoll ( const wchar_t* wStr ) const ;
int32_t compcoll ( const char* uStr ) const ;
int32_t compcoll ( const gString& bs ) const ;

//* Scan the data for a matching substring and if found, return the index at     *
//* which the first substring match begins.                                      *
//*                                                                              *
//* Actual comparison is always performed against the 'wide' character array     *
//* using wcsncasecmp (or wcsncmp). Null terminator character IS NOT included    *
//* in the comparison. These comparisons are not locale dependent.               *
//*                                                                              *
//* Input  : src    : source data to be matched, one of the following:           *
//*                   -- pointer to a UTF-8 string                               *
//*                   -- pointer to a wchar_t string                             *
//*                   -- a gString object containing the source (by reference)   *
//*                   -- a single, wchar_t character                             *
//*          offset : (optional, ZERO by default)                                *
//*                   character index at which to begin search                   *
//*                   -- if out-of-range, then same as if not specified          *
//*          casesen: (optional, 'false' by default)                             *
//*                   if 'false', then scan IS NOT case sensitive                *
//*                   if 'true, then scan IS case sensitive                      *
//*          maxcmp : (optional, (-1) by default)                                *
//*                   -- if not specified, then scan for a match of all          *
//*                      characters in 'src', beginning at 'offset'              *
//*                      (nullchar terminator is not included in search)         *
//*                   -- if specified, then scan for a match of only the first   *
//*                      'maxcmp' characters of 'src'                            *
//*                   -- if out-of-range, then same as if not specified          *
//* Returns: index of matching substring or (-1) if no match found               *
//*          Note: This is the wchar_t character index, NOT a byte index         *
int32_t find ( const wchar_t* src, int32_t offset = 0, 
               bool casesen = false, int32_t maxcmp = -1 ) const ;
int32_t find ( const char* src, int32_t offset = 0, 
               bool casesen = false, int32_t maxcmp = -1 ) const ;
int32_t find ( const uint8_t* src, int32_t offset = 0, 
               bool casesen = false, int32_t maxcmp = -1 ) const ;
int32_t find ( const gString& src, int32_t offset = 0, 
               bool casesen = false, int32_t maxcmp = -1 ) const ;
int32_t find ( wchar_t src, int32_t offset = 0, 
               bool casesen = false, int32_t maxcmp = -1 ) const ;

//* Scan the data for the last occurance of the matching substring and if        *
//* found, return the index at which the substring match occurs.                 *
//*                                                                              *
//* Actual comparison is always performed against the 'wide' character array     *
//* using wcsncasecmp (or wcsncmp). Null terminator character IS NOT included    *
//* in the comparison. These comparisons are not locale dependent.               *
//*                                                                              *
//* Input  : src    : source data to be matched, one of the following:           *
//*                   -- pointer to a wchar_t string                             *
//*                   -- pointer to a UTF-8 string                               *
//*                   -- a single, wchar_t character                             *
//*                   -- a gString object containing the source (by reference)   *
//*          casesen: (optional, 'false' by default)                             *
//*                   if 'false', then scan IS NOT case sensitive                *
//*                   if 'true, then scan IS case sensitive                      *
//* Returns: index of last matching substring or (-1) if no match found          *
//*          Note: This is the wchar_t character index, NOT a byte index         *
int32_t findlast ( const wchar_t* src, bool casesen = false ) const ;
int32_t findlast ( const char* src, bool casesen = false ) const ;
int32_t findlast ( const uint8_t* src, bool casesen = false ) const ;
int32_t findlast ( const wchar_t src, bool casesen = false ) const ;
int32_t findlast ( const gString& src, bool casesen = false ) const ;

//* This method is very similar to the 'find()' method above, but instead of     *
//* returning the index to the beginning of the substring, returns the index     *
//* of the character which FOLLOWS the substring.                                *
//*                                                                              *
//* Input  : src    : source data to be matched, one of the following:           *
//*                   -- pointer to a UTF-8 string                               *
//*                   -- pointer to a wchar_t string                             *
//*                   -- a single, wchar_t character                             *
//*                   -- a gString object containing the source (by reference)   *
//*          offset : (optional, ZERO by default)                                *
//*                   character index at which to begin search                   *
//*                   -- if out-of-range, then same as if not specified          *
//*          casesen: (optional, 'false' by default)                             *
//*                   if 'false', then scan IS NOT case sensitive                *
//*                   if 'true, then scan IS case sensitive                      *
//* Returns: index of the character which follows the matching substring         *
//*            or (-1) if no match found                                         *
//*          Note: This is the wchar_t character index, NOT a byte index.        *
//*          Note: Index will never reference data beyond the NULL terminator.   *
int32_t after ( const char* src, int32_t offset = 0, bool casesen = false ) const ;
int32_t after ( const uint8_t* src, int32_t offset = 0, bool casesen = false ) const ;
int32_t after ( const wchar_t* src, int32_t offset = 0, bool casesen = false ) const ;
int32_t after ( const wchar_t src, int32_t offset = 0, bool casesen = false ) const ;
int32_t after ( const gString& src, int32_t offset = 0, bool casesen = false ) const ;

//* Scan the data beginning at the specified offset and moving toward the head   *
//* of the string (toward offset zero). Locate the matching substring and if     *
//* found, return the index of the first match.                                  *
//*                                                                              *
//* Actual comparison is always performed against the 'wide' character array     *
//* using wcsncasecmp (or wcsncmp). Null terminator character IS NOT included    *
//* in the comparison. These comparisons are not locale dependent.               *
//*                                                                              *
//* Input  : src    : source data to be matched, one of the following:           *
//*                   -- pointer to a UTF-8 string                               *
//*                   -- pointer to a wchar_t string                             *
//*                   -- a single, wchar_t character (by reference)              *
//*                   -- a gString object containing the source (by reference)   *
//*          offset : (optional, -1 by default, indicating index of null         *
//*                    terminator minus one)                                     *
//*                   character index at which to begin search                   *
//*                   -- if out-of-range, then same as if not specified          *
//*          casesen: (optional, 'false' by default)                             *
//*                   if 'false', then scan IS NOT case sensitive                *
//*                   if 'true, then scan IS case sensitive                      *
//*                                                                              *
//* Returns: index of the first (leftmost) character of the matching substring   *
//*          or (-1) if no match found                                           *
//*          Note: This is the wchar_t character index, NOT a byte index         *
int32_t findr ( const char* src, int32_t offset = -1, bool casesen = false ) const ;
int32_t findr ( const uint8_t* src, int32_t offset = -1, bool casesen = false ) const ;
int32_t findr ( const wchar_t* src, int32_t offset = -1, bool casesen = false ) const ;
int32_t findr ( const wchar_t  src, int32_t offset = -1, bool casesen = false ) const ;
int32_t findr ( const gString& src, int32_t offset = -1, bool casesen = false ) const ;

//* Scan the text and locate the first character which DOES NOT match the        *
//* specified character. This method is used primarily to scan past the end of   *
//* a sequence of space (' ') (20 hex) characters, but may be used to skip       *
//* over any sequence of a single, repeated character.                           *
//*                                                                              *
//* See also the 'scan' method which scans to the first non-whitespace           *
//* character.                                                                   *
//*                                                                              *
//* Input  : srcChar: (optional, L' ' by default) character to be skipped over   *
//*          offset : (optional, ZERO by default)                                *
//*                   if specified, the character offset into the array at which *
//*                   to begin the scan.                                         *
//*                                                                              *
//* Returns: a) If successful, returns the index of first character which        *
//*             DOES NOT match specified character.                              *
//*          b) If the scan finds no character which is different from the       *
//*             specified character, OR if 'offset' is out of range, OR if the   *
//*             specified character is the null character, the return value      *
//*             indexes the null terminator of the array.                        *
//*          Note: This is the wchar_t character index, NOT a byte index         *
int32_t findx ( wchar_t srcChar = L' ', int32_t offset = 0 ) const ;

//* Scans the text array and returns the index of the first non-whitespace       *
//* character found.                                                             *
//* Whitespace characters are:                                                   *
//*    0x20   single-column ASCII space                                          *
//*    0x3000 two-column CJK space                                               *
//*    0x0A   linefeed character                                                 *
//*    0x0D   carriage-return character                                          *
//*    0x09   tab character                                                      *
//*    0x0B   vertical-tab character                                             *
//*    0x0C   formfeed character                                                 *
//*                                                                              *
//* Input  : offset : (optional, ZERO by default)                                *
//*                   if specified, the character offset into the array at which *
//*                   to begin the scan.                                         *
//*                                                                              *
//* Returns: a) If successful, returns the index of first non-whitespace         *
//*             character                                                        *
//*          b) If the scan finds no non-whitespace character OR if 'offset'     *
//*             is out of range, the return value indexes the null terminator    *
//*             of the array.                                                    *
//*          Note: This is the wchar_t character index, NOT a byte index         *
int32_t scan ( int32_t offset = 0 ) const ;

//* Scan the text data and extract data according to the specified formatting    *
//* template.                                                                    *
//* (This is an implementation of the standard C-library 'swscanf' function.)    *
//*                                                                              *
//* Input  : fmt  : a format specification template in the style of swscanf(),   *
//*                 sscanf() and related C/C++ functions.                        *
//*                 Template may be either a const char* OR a const wchar_t*.    *
//*                                                                              *
//*          ...  : optional arguments                                           *
//*                 Each optional argument is a POINTER to (address of) the      *
//*                 variable to receive the formatted data.                      *
//*                 - Important Note: There must be AT LEAST as many optional    *
//*                   arguments as the number of format specifiers defined in    *
//*                   the formatting template. Excess arguments will be          *
//*                   ignored; HOWEVER, too few arguments will return an         *
//*                   error condition. (see below)                               *
//*                                                                              *
//* Returns: number of items captured and converted                              *
//*          returns 0 if:                                                       *
//*            a) number of format specifications in 'fmt' > gsFormMAXARGS.      *
//*            b) number of format specifications in 'fmt' > number of           *
//*               optional arguments (pointers to target variables) provided.    *
int32_t gscanf ( const wchar_t* fmt, ... ) const ;
int32_t gscanf ( const char* fmt, ... ) const ;

//* Scan the text data and extract data according to the specified formatting    *
//* template.                                                                    *
//* (This is an implementation of the standard C-library 'swscanf' function.)    *
//*                                                                              *
//* Input  : offset: character offset at which to begin the scan                 *
//*                  Important Note: This IS NOT a byte offset.                  *
//*                  If offset < 0 || offset > length of data, offset will       *
//*                  be silently set to 0.                                       *
//*          fmt   : a format specification template in the style of swscanf(),  *
//*                  sscanf() and related C/C++ functions.                       *
//*                  Template may be either a const char* OR a const wchar_t*.   *
//*                                                                              *
//*          ...   : optional arguments                                          *
//*                  Each optional argument is a POINTER to (address of) the     *
//*                  variable to receive the formatted data.                     *
//*                  - Important Note: There must be AT LEAST as many optional   *
//*                    arguments as the number of format specifiers defined in   *
//*                    the formatting template. Excess arguments will be         *
//*                    ignored; HOWEVER, too few arguments will return an        *
//*                    error condition. (see below)                              *
//*                                                                              *
//* Returns: number of items captured and converted                              *
//*          returns 0 if:                                                       *
//*            a) number of format specifications in 'fmt' > gsFormMAXARGS.      *
//*            b) number of format specifications in 'fmt' > number of           *
//*               optional arguments (pointers to target variables) provided.    *
int32_t gscanf ( int32_t offset, const wchar_t* fmt, ... ) const ;
int32_t gscanf ( int32_t offset, const char* fmt, ... ) const ;


//********************************************************************************
//**:G:                         Output Group                                    **
//********************************************************************************

//* Copy gString text to specified target buffer. (source data unchanged)        *
//*                                                                              *
//* Input  : uTarget : pointer to target array to receive UTF-8-encoded text     *
//*          maxBytes: maximum number of bytes to copy (incl. null terminator)   *
//*          maxCols : (optional, default == -1, i.e. count characters only)     *
//*                    maximum number of display-columns to copy                 *
//* Returns: number of bytes copied (incl. null terminator)                      *
int32_t copy ( char* uTarget, int32_t maxBytes, int32_t maxCols=-1 ) const ;
int32_t copy ( uint8_t* uTarget, int32_t maxBytes, int32_t maxCols=-1 ) const ;

//* Copy gString text to specified target buffer. (source data unchanged)        *
//*                                                                              *
//* Input  : wTarget : pointer to target array to receive wchar_t 'wide' text    *
//*          maxChars: maximum number of characters to copy (incl. null)         *
//*          maxCols : (optional, default == -1, i.e. count characters only)     *
//*                    maximum number of display-columns to copy                 *
//* Returns: number of characters copied (incl. null terminator)                 *
int32_t copy ( wchar_t* wTarget, int32_t maxChars, int32_t maxCols=-1 ) const ;

//* Copy the specified character range to specified target buffer.               *
//*                                                                              *
//* If target buffer is a char*, then data returned is a UTF-8 text string.      *
//* If target buffer is a wchar_t*, then data returned is a wchar_t (wide)       *
//*   text string.                                                               *
//*   IMPORTANT NOTE: It is the caller's responsibility to specify               *
//*   a target buffer large enough to hold the data. Recommended:                *
//*      wchar_t wbuff[gsALLOCMED]; or char ubuff[gsALLOCMED * 4] respectively.  *
//* If target buffer is a gString object, then both UTF-8 and wchar_t data are   *
//* returned (with no chance of target buffer overflow :).                       *
//*                                                                              *
//* Input  : trg     : (by reference, initial contents ignored)                  *
//*                    receives null-terminated contents of specified            *
//*                    character range                                           *
//*          offset  : character index at which substring begins                 *
//*                    (this IS NOT a byte index)                                *
//*          charCnt : number of characters to copy (not incl. NULL terminator)  *
//*                                                                              *
//* Returns: if target is a wchar_t* or gString object, then returns number of   *
//*            characters written to target (not including the NULL terminator)  *
//*          if target is a char*, then returns number of bytes written to       *
//*            target (not including the NULL terminator)                        *
//*                                                                              *
//*          Note: returns ZERO if either 'offset' or 'charCnt' out of range     *
//*              Note that if 'charCnt' extends beyond the end of the source     *
//*              data, then the available data are returned.                     *
int32_t substr (    char* trg, int32_t offset, int32_t charCnt ) const ;
int32_t substr ( uint8_t* trg, int32_t offset, int32_t charCnt ) const ;
int32_t substr ( wchar_t* trg, int32_t offset, int32_t charCnt ) const ;
int32_t substr ( gString& trg, int32_t offset, int32_t charCnt ) const ;

//* Insertion operator: Insert the contents of the gString object into the       *
//* standard output stream.                                                      *
//* Overloaded operator allows access to the 'wcout' (wide) standard output      *
//* stream OR access to the 'cout' (narrow) standard output stream.              *
//* IMPORTANT NOTE: It is strongly recommended that for display output,          *
//*                 the 'wcout' (wide) stream version be used exclusively.       *
//*                      !! NON-MEMBER METHOD !!                                 *
//*                                                                              *
//* Input  : implied reference to output stream                                  *
//*          implied reference to gString object                                 *
//* Returns: reference to the specified output stream                            *
friend std::wostream& operator << ( std::wostream& os, const gString& bsref ) ;
friend std::ostream& operator << ( std::ostream& os, const gString& bsref ) ;

#if DEBUG_GSTRING != 0
//* Methods For Debugging Only:                                                  *
//* Report the current contents of the data members.                             *
void dumpGstring ( const wchar_t*& gstr, const char*& ustr, const short*& cwid, 
                   int32_t& gsw, int32_t& gsu, int32_t& bsch, int32_t& bsco, 
                   int32_t& utfb, bool& isas ) const ;
void dbMsg ( gString& bsmsg ) const ;
#endif   // DEBUG_GSTRING

//******************************
//** Private Methods and Data **
//******************************
private:
//* Data-member Initialization Group *
int32_t allocate ( int32_t walloc ) ;
int32_t reallocate ( int32_t walloc ) ;
bool  reallocate ( const char* usrc, const wchar_t* wsrc = NULL ) ;
void  reset ( bool initAll=true ) ;
bool  buffer_overrun ( void ) ;

//* Character Encoding and Recoding *
void  utf8_2_utf32 ( const char* usrc, int32_t charLimit = -1 ) ;
void  bytewise_u2w ( const char* usrc, int32_t charLimit ) ;
void  utf32_2_utf8 ( const wchar_t* wsrc = NULL, int32_t charLimit = -1 ) ;
void  bytewise_w2u ( int32_t charLimit ) ;

int   gsForm_2_gs ( const gsForm& gsf, wchar_t* wsrc, int len ) ;
void  limitBytes ( int32_t maxBytes ) ;
void  columnCount ( int32_t maxCols = -1 ) ;
void  binaryFormat ( wchar_t* convBuff, wchar_t convType, wchar_t sepType, 
                     long long int intData, short dataType, short grpType, 
                     bool append ) ;
int32_t gscanf ( const gsForm& gsf, int32_t argCount, int32_t offset ) const ;
bool  replace ( const gString& src, const gString& newtxt, 
                int32_t offset, bool casesen, bool all ) ;
int32_t textReverse_all ( bool punct ) ;
int32_t composeFieldwidthBugFix ( char convType, wchar_t* wsrcPtr, int32_t wsrcSpace, 
                                  const wchar_t* fmt, const gString& gsSrc ) ;

//* Integer Formatting Group *
bool  formatQInt ( unsigned long long iVal, short fWidth, bool lJust, 
                   bool sVal, bool sign, bool kibi, fiUnits units ) ;
bool  fqiRound ( gString& gt, short fWidth ) ;
bool  fqiThreeColumn ( gString& gt, gString& suffix, double dblVal, short vRange,
                       bool sVal, bool sign, bool kibi ) ;
const wchar_t* fqiAppendSuffix ( short& vRange, double dblVal, fiUnits units, bool sVal ) ; 
bool  fqiBumpSuffix ( wchar_t* wsrc, gString& gtSuffix ) ;

//** Private Data Members **
//** -------------------- **
wchar_t* gStr ;               // text data in wchar_t 'wide' format
char*    uStr ;               // text data in UTF-8 encoded format
short*   cWid ;               // column width for each character in gStr
int32_t  gsw ;                // size of dynamic allocation in 32-bit words
int32_t  gsu ;                // size of dynamic allocation in 8-bit bytes
int32_t  gsChars ;            // number of characters represented (incl. null)
int32_t  gsCols ;             // display columns needed to display gStr array
int32_t  utfBytes ;           // number of bytes in UTF-8 data (incl. null)
bool     isAscii ;            // 'true' if data are pure, 7-bit ASCII, else 'false'
// Note that isAscii is unitialized by default and is valid only after 
// a call to the isASCII() method
} ;

#endif   // GSTRING_INCLUDED

