Monday, December 2, 2024

ios_base

Overview
ios_base is the base class for all the iostream classes.

Details
The class ios_base is a multipurpose class that serves as the base class for all I/O stream classes. It defines multiple category of flags and enumeration. It also maintains several kinds of data as discussed in detail below.

iostate flags
iostate flags indicate the result of each IO operation. They are checked by stream classes for their success or failure.  These are bitmask type flags that can be ORed. The following describes different values.
NameDescription
goodbitAll is fine.
eofbit eof is reached on the stream during read operation.
failbitPrevious operation failed. Examples: reading error or file not found
badbitPrevious operation due to fatal error. Example, out of memory.
Note it's possible to have multiple flags set. i.e., eofbit and failbit set at the same time.

openmode
The openmode flags indicate how the streams such as disk files or memory streams can be opened for IO operations such as read, write or append.  These are used in calls such as fopen(). These are bitmask type flags that can be ORed. The following describes different values.
NameDescription
inOpen file for reading.
outOpen file for writing.
ateSet the stream's position indicator to the end of the stream on opening.
appSet the stream's position indicator to the end of the stream before each output operation.
truncAny current content is discarded, assuming a length of zero on opening.
binaryConsider stream as binary rather than text.
Note it's possible to have multiple flags set. i.e., in | out set at the same time.

Note that in case of ate, writes can be on done anywhere in the stream. For example, begin or middle. In case of app, writes can be done only in the end.
Note that difference between text and binary files is that in a text file individual lines are demarcated by a newline character \n or \r\n. In case of binary files there are no such demarcation.

seekdir
seekdir enumerations indicate the position of the file pointer during a seek operation by the streams.
NameDescription
begThe beginning of a stream.
curThe current position of stream position indicator.
endThe ending of a stream.

Formatting
ios_base class provides several infrastrures to format data from both input and output streams. The following describes it in detail.

fmtflags (Independent Flags)
These flags enable formatting individually. To set, use 1st version of setf().
FlagDescription
boolalphaInserts and extracts bool values in alphabetic format(true/false). By default numeric format(1/0) is used.
showposGenerates a + sign in non-negative generated numeric output. By default no sign is generated.
showpointAlways generates a decimal-point in generated floating-point output. By default point is generated only if mantissa is not zero.
showbaseGenerates a prefix indicating the numeric base of a generated integer output. By default no baseis generated.
skipwsSkips leading white space before certain input operations. By default white space is not skipped.
unitbufFlushes output after each out formatting operation. By default output is not flushed for each out formatting operation.
uppercaseReplaces certain lowercase letters with their uppercase equivalents in generated output. By default no case is generated.

fmtflags (Group Fields)
Each of these fields are a collection of multiple  bitmask flags. To set a flag, the second version of setf() should be used.
FlagDescription
decUses decimal base for integer Input and Output.
octUses octal base for integer Input and Output.
hexUses hex base for integer Input and Output.
basefielddec | oct | hex. Used for masking operations.
leftleft adjustment (adds fill characters to the end).
rightright adjustment (adds fill characters to the beginning).
internalinternal adjustment (adds fill characters to the internal designated point)
adjustfieldleft | right | internal. Used for masking operations
fixedwrite floating point values in fixed-point notation.
scientificwrite floating-point values in scientific notation.
floatfieldfixed| scientific. Used for masking operations.

These methods are provided to set and unset above formatting flags.
NameDescription
  1. fmtflags flags() 
  2. fmtflags flags
    (fmtflags f)
  1. Returns the format flags currently selected in the stream.
  2. Sets new format flags f for the stream, returning its old value.
  1. fmtflags setf
    (fmtflags f)
  2. fmtflags setf
    (fmtflags f, fmtflags mask)
  1. Adds f to the stream's format flags, as if a call to flags(f|flags()). Generally used to set independent format flags which can also be unset directly with member unsetf.
  2. Sets the stream's format flags whose bits are set in both f and mask, and clears the format flags whose bits are set in mask but not in f, as if a call to flags((f&mask)|(flags()&~mask)). Generally used to set a value for one of the selective flags, using one of the field bitmasks as the mask argument.
Both return the value of the stream's format flags before the call.
void unsetf
(fmtflags mask)
Clears the formgt flags selected in mask. It can be a combination of the formatting flags constants.
Example
/* prints
0x64
0x64
*/
// using fmtflags as class member constants:
cout.setf (ios_base::hex , ios_base::basefield); 
cout.setf (ios_base::showbase); 
cout << 100 << endl;

// using fmtflags as a type:
auto ff = cout.flags(); 
ff &= ~cout.basefield; // unset basefield bits
ff |= cout.hex; // set hex
ff |= cout.showbase; // set showbase
cout.flags(ff); 
cout << 100 << endl;
  1. streamsize precision()
  2. streamsize precision
    (streamsize prec)

Get/Set floating-point decimal precision. It determines the maximum number of digits to be written for a floating point value. How this is interpreted depends on the floatfield format flag. i.e., fixed or scientific or it is unset (default notation).
  1. Returns the value of the current floating-point precision field for the stream.
  2. sets current floating-point precision field for the stream to a new value and returns the previous value
Using the default floating-point notation, the precision field specifies the maximum number of meaningful digits to display in total counting both those before and those after the decimal point. Notice that it is not a minimum, and therefore it does not pad the displayed number with trailing zeros if the number can be displayed with less digits than the precision.
In both the fixed and scientific notations, the precision field specifies exactly how many digits to display after the decimal point, even if this includes trailing decimal zeros. The digits before the decimal point are not relevant for the precision in this case.
  1. streamsize width()
  2. streamsize width
    (streamsize w)
  1. Returns the current value of the field width.
  2. Sets a new field width for the stream with w and returns the previous value of the field width.
The field width determines the minimum number of characters to be written in some output representations. If the standard width of the representation is shorter than the field width, the representation is padded with fill characters at a point determined by the format flag adjustfield (one of left, right or internal).
Example
/* prints
812|813       815
8.31E+02 8.00E+02
*/    
auto original_flags = cout.flags();
cout<< 812<<'|';
cout.setf(ios_base::left,ios_base::adjustfield);
cout.width(10); 
cout << 813 << 815 << endl;
cout.unsetf(ios_base::adjustfield);
cout.precision(2);
cout.setf(ios_base::uppercase | ios_base::scientific);
cout << 831.0 << ' ' << 8e2;
cout.flags(original_flags);

Internal extensible array
The internal extensible array is a general-purpose array of objects of type long (if accessed with member iword) or void* (if accessed with member pword).
These static  methods are provided to set and unset above formatting flags.
NameDescription
int xalloc()
Returns a unique (program-wide) index value that can be used to access one long and one void* elements in the private storage of std::ios_base by calling iword() and pword(). The call to xalloc does not allocate memory.
Effectively increments the next available unique index.

long& iword(int idx)


If iarray is a null pointer, allocates an array of longs of sufficient size, and stores a pointer to its first element in iarray. The function then extends the array pointed to by iarray, as necessary, to include the element iarray[idx]. Each newly allocated element of the array is initialized to 0. The reference returned may become invalid after another call to the object's iword() member with a different index, after a call to its copyfmt() member, or when the object is destroyed. If the function fails, it sets failbit, which may throw an exception. On success, the function returns iarray[idx]; otherwise, a valid long& initialized to 0.
Example
// custom manipulator with per-stream static data:
ostream& Counter (ostream& os) 
{
  const static int index = os.xalloc();
  return os << ++os.iword(index);
}
/* prints
1: first line
2: second line
3: third line
1: error line
*/

  cout << Counter << ": first line" << endl;
  cout << Counter << ": second line" << endl;
  cout << Counter << ": third line" << endl;
  // cerr has its own count
  cerr << Counter << ": error line" << endl; 
void*& pword(int idx)If parray is a null pointer, allocates an array of void* of sufficient size, and stores a pointer to its first element in parray. The function then extends the array pointed at by parray, as necessary, to include the element parray[idx]. Each newly allocated element of the array is initialized to 0. The reference returned may become invalid after another call to the object's pword member with a different index, after a call to its copyfmt() member, or when the object is destroyed. If the function fails, it sets failbit, which may throw an exception. On success, the function returns parray[idx]; otherwise, a valid void*& initialized to 0.
Example
// custom manipulator that uses stored pointer:
ostream& StreamName (ostream& os) 
{
  const char* name = static_cast<const char*>(os.pword(name_index));
  if (name) os << name;
  else os << "(unknown)";
  return os;
}

/*
prints
standard output stream
standard error stream
(unknown)
*/
    
  SetStreamName(cout, "standard output stream");
  SetStreamName(cerr, "standard error stream");
  cout << StreamName << '\n';
  cerr << StreamName << '\n';
  clog << StreamName << '\n';

events and callback
This discusses registering a call back on some specific events during the lifetime of a stream object.

events 
events enumerations are the events that are raised during a lifetime of an stream.
NameDescription
erase_eventRaised  on ~ios_base() or basic_ios::copyfmt() (before the copy of members takes place).
imbue_eventRaised  when a new locale is being imbued in the stream object.
copyfmt_eventRaised on basic_ios::copyfmt() (after the copy of members takes place, but before the exception settings are copied).

register_callback
NameDescription
void register_callback
(event_callback fn, int index)
Registers a user-defined event_callback function fn which will be called when events listed above occur. The parameter index is an unique index usually obtained by calling xalloc().

Syntax
typedef void (*event_callback) (event ev, ios_base& obj, int index)
The event_callback function will be called with the arguments 
ev: an event mapped to one of the enumerations events , 
obj: the stream object 
index: index passed during  register_callback  call.

The callbacks are called in the reverse order of registration. The user-defined callback function is not allowed to throw exceptions.
Once registered, a callback cannot be deregistered: it remains a part of the stream object for the rest of its lifetime. 

Example
void cb(std::ios::event ev, std::ios_base& stream, int index)
{
  switch (ev)
  {
    case stream.copyfmt_event:
      std::cout << "copyfmt_event\n"; break;
    case stream.imbue_event:
      std::cout << "imbue_event\n"; break;
    case stream.erase_event:
      std::cout << "erase_event\n"; break;
  }
}

/* prints
imbue_event
erase_event
*/    
  std::ofstream filestr;
  filestr.register_callback (cb,filestr.xalloc());
  filestr.imbue (std::cout.getloc());

sync_with_stdio 
NameDescription
bool sync_with_stdio
(bool sync = true)
This is a static method that toggles on or off synchronization of all the iostream standard streams with their corresponding standard C streams. Boolean parameter indicating whether synchronization is to be turned on or off. It returns previous value.
It's intended to be called before the program performs its first input or output operation. This potentially can give a performance boost.

By default, iostream objects and cstdio streams are synchronized.

If the streams are synchronized, a program can mix iostream operations with stdio operations, and their observable effects are guaranteed to follow the same order as used in the thread.

Notice that this is a static member function, and a call to this function using this member of any stream object toggles on or off synchronization for all standard iostream objects.

Init 
This a subclass defined under ios_base. It's used to ensure that the 8 predefined console based C++ streams (cin, cout, clog, cerr, wcin, wcout, wclog, wcerr) are properly initialized and destructed. The class tracks how many instances of it are created and initializes the C++ streams when the first instance is constructed as well as flushes the output streams when the last instance is destructed.

failure
This a subclass defined under ios_base. It's derived from system_error exception class.  It serves as the base class for the exceptions thrown by the elements of the standard input/output library.
These errors are typically categorized either in the iostream_category (if they relate to the operations of the library) or in the system_category (if the error arises from the system). Although the specifics are implementation-defined.

The library implementation may use values of type io_errc to portably identify error conditions of the iostream_category.

Example
/*prints
Caught an ios_base::failure.
Explanatory string: basic_ios::clear: iostream error
Error code: iostream:1
*/

 ifstream f("doesn't exist");
 
    try
    {
        f.exceptions(f.failbit);
    }
    catch (const ios_base::failure& e)
    {
        cerr << "Caught an ios_base::failure." << endl
                  << "Explanatory string: " << e.what() << endl
                  << "Error code: " << e.code() << endl;
    }


locale
Allows to inject a different locale and get currently active locale.
These methods are provided to set and unset above formatting flags.
NameDescription
locale imbue
(const locale& loc)
Injects  a different locale loc to the stream as the new locale object to be used with locale-sensitive operations.
Returns the locale object associated with the stream before the call.
Before that, the function calls all functions registered through member register_callback() with imbue_event as first argument.
Standard stream classes do not inherit this member, but inherit basic_ios::imbue() instead, which calls this function, but also imbues the locale to the associated stream buffer, if any.
Example
/*prints
 Mi 04 Dez 2024 19:30:32 UTC UTC
 */
    time_t t = time(nullptr);
    tm tm = *localtime(&t);
 
    cout.imbue(std::locale("de_DE.utf8"));
    cout << put_time(&tm, "%c %Z") << endl;
locale getloc()
Returns the locale associated with the stream.


No comments:

Post a Comment