# SFBPrintf.h File Reference

Support for simple packet-customized printf- and scanf-like functions. More...

`#include "SFBTypes.h"`
`#include <stdarg.h>`

Include dependency graph for SFBPrintf.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

## Typedefs
typedef void(* | CustomPrintfHandler )(u8 face, void *arg, bool alt, int width, bool zerofill)
| The declaration of a function that can perform custom formatting during a printf(-family) formatting operation.
typedef bool(* | CustomPacketScanfHandler )(u8 *packet, void *arg, bool alt, int width)
| The declaration of a function that can perform custom input scanning during a packetScanf(-family) reading operation.
## Enumerations
enum | LoggingLevels { LOGLEVEL_NONE, LOGLEVEL_QUIET, LOGLEVEL_NORMAL, LOGLEVEL_VERBOSE, LOGLEVEL_DEBUG }
## Functions
void | setLogLevel (int n)
| Set the logging level to n.
int | getLogLevel ()
| Return the current logging level.
void | setLogFace (u8 face)
| Set the log face.
u8 | getLogFace ()
| Return the current log face.
void | pprintf (const char *format,...)
| Convenience shorthand for printing to all available physical faces.
void | facePrintf (u8 face, const char *format,...)
| Formatted printing to the specified face.
void | vfacePrintf (u8 face, const char *format, va_list &ap)
| Formatted printing to the specified face, through a supplied `va_list`.
u32 | packetScanf (u8 *packet, const char *format,...)
| Formatted reading from a packet into individual variables.
u32 | vPacketScanf (u8 *packet, const char *format, va_list &ap)
void | vfaceLogf (int includeTimestamp, int level, u8 face, const char *format, va_list &ap)
void | logf (int level, const char *format,...)
void | logNormal (const char *format,...)
| If getLogLevel() is at least LOGLEVEL_NORMAL, print "Ln " plus a timestamp, plus as directed by format, to the current getLogFace().
void | logVerbose (const char *format,...)
| If getLogLevel() is at least LOGLEVEL_VERBOSE, print "Lv " plus a timestamp, plus as directed by format, to the current getLogFace().
void | logDebug (const char *format,...)
| If getLogLevel() is at least LOGLEVEL_DEBUG, print "Ld " plus a timestamp, plus as directed by format, to the current getLogFace().
void | logQuiet (const char *format,...)
| If getLogLevel() is at least LOGLEVEL_QUIET, print "Lq " plus a timestamp, plus as directed by format, to the current getLogFace().
void | msgf (int level, const char *format,...)
void | msgNormal (const char *format,...)
| If getLogLevel() is at least LOGLEVEL_NORMAL, print "Lq " plus as directed by format, to the current getLogFace().
void | msgVerbose (const char *format,...)
| If getLogLevel() is at least LOGLEVEL_VERBOSE, print "Lv " plus as directed by format, to the current getLogFace().
void | msgDebug (const char *format,...)
| If getLogLevel() is at least LOGLEVEL_DEBUG, print "Ld " plus as directed by format, to the current getLogFace().
void | msgQuiet (const char *format,...)
| If getLogLevel() is at least LOGLEVEL_QUIET, print "Lq " plus as directed by format, to the current getLogFace().

## Detailed Description

Support for simple packet-customized printf- and scanf-like functions.

Author:
  David H. Ackley.

Date:
  (C) 2009 All rights reserved.

Code License:
  The GNU Lesser General Public License

License Note:
  All code samples shown in documentation are placed into the public domain.

## Typedef Documentation

typedef bool(* CustomPacketScanfHandler)(u8 *packet, void *arg, bool alt, int width)

The declaration of a function that can perform custom input scanning during a packetScanf(-family) reading operation.

A CustomPacketScanfHandler is established during any given packetScanf call by using the Z code and passing an argument of type CustomPacketScanfHandler. Once established, that CustomPacketScanfHandler is invoked via the z code and passing an argument of type void*, which will become the arg parameter to the CustomPacketScanfHandler function. When the CustomPacketScanfHandler is invoked, it reads from the supplied packet however it wishes to, either respecting, or not, the width and alt arguments, as it chooses.

If the return value from a CustomPacketScanfHandler is `true`, that means a successful z scan and store was performed, and the total matches returned by the packetScanf should be increased by 1, and the packet scanning should continue. If the return value is `false`, that means a scanning error occurred during the z processing, and the packetScanf should be stopped at this point.

The Z code may be used multiple times in a single packetScanf call, and the most-recent Z invocation determines what CustomPacketScanfHandler is called for any given z. It is an error if a z code is invoked without a prior Z code, or if the argument to the most recent prior Z is null, and the code will die blinking E_API_NULL_HANDLER.

See also CustomPrintfHandler.

Since:
  0.9.15

typedef void(* CustomPrintfHandler)(u8 face, void *arg, bool alt, int width, bool zerofill)

The declaration of a function that can perform custom formatting during a printf(-family) formatting operation.

A CustomPrintfHandler is established during any given printf call by using the Z code and passing an argument of type CustomPrintfHandler. Once established, that CustomPrintfHandler is invoked via the z code and passing an argument of type void*, which will become the arg parameter to the CustomPrintfHandler function. When the CustomPrintfHandler is invoked, it prints whatever it likes to face, either respecting, or not, the width, zerofill, and alt arguments, as it chooses.

Additional usage notes:

- The Z code may be used multiple times in a single printf call, in which case the most-recent Z invocation determines what CustomPrintfHandler is called.
- It is an error if a z code is invoked without a prior Z code, or if the argument to the most recent prior Z is null, and the code will die blinking E_API_NULL_HANDLER.
- An established CustomPrintfHandler association is local to the current printf invocation, lasting until the next Z code or to the end of the current format string is reached, whichever comes first.
- It is possible to call a printf(-family) function recursively from inside a CustomPrintfHandler function. Such a recursive call will have no CustomPrintfHandler established within it unless and until its format specifies one via its own Z code.

See also CustomPacketScanfHandler.

Since:
  0.9.15

## Enumeration Type Documentation

enum LoggingLevels

Enumerator:

  LOGLEVEL_NONE | When passed to setLogLevel(int), suppress all logging output.
  LOGLEVEL_QUIET | When passed to setLogLevel(int), allow less than normal logging output.
  LOGLEVEL_NORMAL | When passed to setLogLevel(int), allow normal logging output.
  LOGLEVEL_VERBOSE | When passed to setLogLevel(int), allow more than normal logging output.
  LOGLEVEL_DEBUG | When passed to setLogLevel(int), allow all logging output.

## Function Documentation

void facePrintf | ( | u8 | face,
|  | const char * | format,
|  |  | ... |
| ) |  |  |

Formatted printing to the specified face.

Parameters:

  | face | the face code to which the printing shall be directed. This may be a "physical face" code like WEST, an "extended face" code like BRAIN or ALL_FACES or NO_FACES, or a sketch-defined "virtual face" code (such as produced by faceFindFreeFace() and faceSetPrinter()).
  | format | a null-terminated string controlling what is to be printed; see below.
  | ... | a variable sequence of arguments of sufficient number and appropriate types to supply to all of the "% codes" in format with the data they need.

facePrintf() performs simple formatted printing, in the same general style as the C language `printf` functions, but with many restrictions -- for example, there is only limited support for 'field widths'. There are also a few SFB-specific extensions. This documentation presumes familiarity with the use of `printf-like` functions in general, and only documents the specifics of the SFB format codes.

Quick format reference. The following 'percent escape' codes are recognized:

- %c: Print 8 bit character into exactly one output byte.
- %h: Print 16 bit value into exactly two output bytes in 'big endian' network order.
- %l: Print 32 bit value into exactly four output bytes in 'big endian' network order.
- %b: Print 32 bit value in base 2 (using only the characters '0' and '1').
- %o: Print 32 bit value in base 8 (using only the characters '0' through '7').
- %d: Print 32 bit value in base 10 (using only the characters '0' through '9').
- %x: Print 32 bit value in base 16 (using only the characters '0' through '9' and 'A' through 'F' for 10 to 15).
- %t: Print 32 bit value in base 36 (using only the characters '0' through '9' and 'A' through 'Z' for 10 to 35).
- %F: Print the 'face code' (e.g., 'N' for North) in one output byte
- %f: Print double value in floating point with two decimal places.
- %s: Print null-terminated string given a (const char *) pointer to the first byte
- %p: Print a packet given a (const u8 *) pointer to the packet
- %%: Print a percent sign
- %\n: Print a checkbyte and then a newline (as by printlnCheckByte).

The '#' modifier character may be added to certain conversions to achieve special purposes, as follows:

- For the %d code, '#' causes the argument to be printed as an unsigned value rather than signed.
- For the %b, %o, %x, and %t codes, '#' causes the argument to be printed as a signed value rather than unsigned.
- For the %c code, '#' causes a 'non-printing' char arg to be printed as four bytes -- a '[', two hex digits, and a ']' -- rather than printing the char value directly.
- For the %p code, '#' causes any 'non-printing' bytes (or '%' bytes) of the packet to be printed as three bytes each -- a '%', followed by two hex digits -- rather than printing the byte values directly.

Since 0.9.7, there is limited support for field widths (a.k.a. padding and filling), with the following restrictions:

- Padding is supported only on the formatted integer conversions --%b, %o, %d, %x, and %t,
- Only padding on the left is supported (so, only 'right-justified columns').
- Padding is always either spaces or zeros; spaces are used unless the field width begins with a '0'.

XXX Still need formatting details; examples.

Blinks:
  E_API_NULL_POINTER if format is null.

Blinks:
  E_API_BAD_FACE if face is not a valid (physical, extended, or defined virtual) face.

Blinks:
  E_API_BAD_FORMAT_CODE if an unrecognized "%" code is encountered in format. (Also occurs if a single "%" is the last character in format.)

Since:
  0.9.7 for field widths

Examples:
  brn.cpp, fifthdirection.cpp, hallucination.cpp, log.cpp, netled.cpp, zformat1.cpp, zformat2.cpp, and zformat3.cpp.

u8 getLogFace | ( |  | ) |

Return the current log face.

See setLogFace(u8) for details.

int getLogLevel | ( |  | ) |

Return the current logging level.

See setLogLevel(int) for details.

void logDebug | ( | const char * | format,
|  |  | ... |
| ) |  |  |

If getLogLevel() is at least LOGLEVEL_DEBUG, print "Ld " plus a timestamp, plus as directed by format, to the current getLogFace().

Otherwise do nothing.

void logNormal | ( | const char * | format,
|  |  | ... |
| ) |  |  |

If getLogLevel() is at least LOGLEVEL_NORMAL, print "Ln " plus a timestamp, plus as directed by format, to the current getLogFace().

Otherwise do nothing.

Examples:
  eeprom1.cpp, eeprom4.cpp, hallucination.cpp, i2cEeprom.cpp, profile2.cpp, profile3.cpp, reorder.cpp, sdcard1.cpp, sdcard2.cpp, sdcard3.cpp, speed4.cpp, trigger.cpp, zformat2.cpp, and zformat3.cpp.

void logQuiet | ( | const char * | format,
|  |  | ... |
| ) |  |  |

If getLogLevel() is at least LOGLEVEL_QUIET, print "Lq " plus a timestamp, plus as directed by format, to the current getLogFace().

Otherwise do nothing.

void logVerbose | ( | const char * | format,
|  |  | ... |
| ) |  |  |

If getLogLevel() is at least LOGLEVEL_VERBOSE, print "Lv " plus a timestamp, plus as directed by format, to the current getLogFace().

Otherwise do nothing.

void msgDebug | ( | const char * | format,
|  |  | ... |
| ) |  |  |

If getLogLevel() is at least LOGLEVEL_DEBUG, print "Ld " plus as directed by format, to the current getLogFace().

Otherwise do nothing.

void msgNormal | ( | const char * | format,
|  |  | ... |
| ) |  |  |

If getLogLevel() is at least LOGLEVEL_NORMAL, print "Lq " plus as directed by format, to the current getLogFace().

Otherwise do nothing.

void msgQuiet | ( | const char * | format,
|  |  | ... |
| ) |  |  |

If getLogLevel() is at least LOGLEVEL_QUIET, print "Lq " plus as directed by format, to the current getLogFace().

Otherwise do nothing.

void msgVerbose | ( | const char * | format,
|  |  | ... |
| ) |  |  |

If getLogLevel() is at least LOGLEVEL_VERBOSE, print "Lv " plus as directed by format, to the current getLogFace().

Otherwise do nothing.

u32 packetScanf | ( | u8 * | packet,
|  | const char * | format,
|  |  | ... |
| ) |  |  |

Formatted reading from a packet into individual variables.

Scanning starts at the current packetCursor() of packet, not necessarily at the beginning, and the packetCursor() of packet is advanced as scanning proceeds.

Parameters:

  | packet | The packet that is to be scanned.
  | format | a null-terminated string controlling what is to be printed; see below.
  | ... | a variable sequence of pointer arguments of sufficient number and appropriate types through which to store values for all the "% codes" in format that require arguments.

With the exceptions of %s, %f, and %p, which are not supported, packetScanf supports the same format codes as facePrintf prints, which see for further description of the format conversions. Note that the pointed-to variables must be appropriate (sizes at least) for the converted type! For example,

      void MyBHandler(u8 * packet) {
        u32 fourBytes; u16 twoBytes; u8 oneByte;
        if (packetScanf(packet,"b%c%d%h",&oneByte,&fourBytes,&twoBytes) != 4)
           return;
        ..
      }

is correct since the sizes of the `oneByte`, `fourBytes`, and `twoBytes` variables match the specified sizes of %c, %d, and %h, respectively.

Since 0.9.9, there is some support for field widths, limited to the %b, %o, %d, %x, and %t conversions only.

packetScanf returns the number of successful matches it made, where a 'match' counts as either a successful '% conversion' or a successful match of a single literal byte of the format string. E.g., given a packet containing "fg123h", `packetScanf`(packet,"fg%dh",&u32var) will return 4 -- one for the 'f', one for the 'g', one for the '%d', and one for the 'h'. (But watch out! Given the same packet, `packetScanf`(packet,"fg%dh\n",&u32var) will return 5 -- including one for the successful matching of the end-of-packet!)

XXX Still need formatting details; examples.

Since:
  0.9.9 for field widths

Examples:
  eeprom1.cpp, netled.cpp, pingpong.cpp, pingpong2.cpp, reorder.cpp, sdcard3.cpp, speed2.cpp, speed3.cpp, speed4.cpp, zformat1.cpp, zformat2.cpp, and zformat3.cpp.

void pprintf | ( | const char * | format,
|  |  | ... |
| ) |  |  |

Convenience shorthand for printing to all available physical faces.

Equivalent to facePrintf(ALL_FACES, format, ...), which see for details of the possible format codes.

Examples:
  profile1.cpp, reorder.cpp, and sdcard3.cpp.

void setLogFace | ( | u8 | face | ) |

Set the log face.

Using this function, logging messages can be directed to any (physical or virtual) face. Default value: ALL_FACES

Examples:
  eeprom4.cpp, and trigger.cpp.

void setLogLevel | ( | int | n | ) |

Set the logging level to n.

Larger values produce more output, smaller values produce less. Initial value is LOGLEVEL_NORMAL.

Parameters:

  | n | Logging level. Can be any int, but only the values LOGLEVEL_NONE, LOGLEVEL_QUIET, LOGLEVEL_NORMAL, LOGLEVEL_VERBOSE, LOGLEVEL_DEBUG really make much sense.

void vfacePrintf | ( | u8 | face,
|  | const char * | format,
|  | va_list & | ap |
| ) |  |  |

Formatted printing to the specified face, through a supplied `va_list`.

See facePrintf(u8 face, const char * format, ...) for details of arguments face and format.