static void printf_iterator_set_type_char()

in sources/printf.c [237:316]


static void printf_iterator_set_type_char(printf_iterator *iterator, char c) {
  Contract(iterator);
  Contract(iterator->sem_type == SEM_TYPE_PENDING);
  Contract(iterator->state == PRINTF_STATE_TYPE);

  CSTR_OF_CHAR(type_string, c);

  // '-' works with all possible type specifications.
  printf_flags valid_flags = PRINTF_FLAGS_MINUS;
  bool_t allows_length_specifier;

  switch (c) {
    case 'd': case 'i': {
      allows_length_specifier = true;
      valid_flags |= PRINTF_FLAGS_PLUS;
      valid_flags |= PRINTF_FLAGS_SPACE;
      valid_flags |= PRINTF_FLAGS_ZERO;
      valid_flags |= PRINTF_FLAGS_COMMA;
      if (iterator->length == PRINTF_LENGTH_LONG_LONG) {
        iterator->sem_type = SEM_TYPE_LONG_INTEGER;
      } else {
        iterator->sem_type = SEM_TYPE_INTEGER;
      }
      break;
    }
    case 'u':
      allows_length_specifier = true;
      valid_flags |= PRINTF_FLAGS_ZERO;
      if (iterator->length == PRINTF_LENGTH_LONG_LONG) {
        iterator->sem_type = SEM_TYPE_LONG_INTEGER;
      } else {
        iterator->sem_type = SEM_TYPE_INTEGER;
      }
      break;
    case 'f': case 'e': case 'E': case 'g': case 'G':
      allows_length_specifier = false;
      valid_flags |= PRINTF_FLAGS_ZERO;
      valid_flags |= PRINTF_FLAGS_BANG;
      valid_flags |= PRINTF_FLAGS_HASH;
      iterator->sem_type = SEM_TYPE_REAL;
      break;
    case 'x': case 'X': case 'o':
      allows_length_specifier = true;
      valid_flags |= PRINTF_FLAGS_ZERO;
      valid_flags |= PRINTF_FLAGS_HASH;
      if (iterator->length == PRINTF_LENGTH_LONG_LONG) {
        iterator->sem_type = SEM_TYPE_LONG_INTEGER;
      } else {
        iterator->sem_type = SEM_TYPE_INTEGER;
      }
      break;
    case 's':
      allows_length_specifier = false;
      valid_flags |= PRINTF_FLAGS_BANG;
      iterator->sem_type = SEM_TYPE_TEXT;
      break;
    case 'c': case 'z': case 'p': case 'n': case 'q': case 'Q': case 'w': {
      // NOTE: 'c' could be supported with codegen changes. It is presently
      // disallowed because it requires a TEXT argument when used in an SQL
      // context, yet it requires an integer argument when used via
      // `sqlite3_mprintf`. The code generator currently cannot handle the
      // latter case correctly.
      printf_iterator_error(iterator, "CQL0416: type specifier not allowed in CQL", type_string);
      return;
    }
    default:
      printf_iterator_error(iterator, "CQL0417: unrecognized type specifier", type_string);
      return;
  }

  if ((iterator->flags | valid_flags) != valid_flags) {
    printf_iterator_error(iterator, "CQL0418: type specifier combined with inappropriate flags", type_string);
    return;
  }

  if (iterator->length != PRINTF_LENGTH_DEFAULT && !allows_length_specifier) {
    printf_iterator_error(iterator, "CQL0419: type specifier cannot be combined with length specifier", type_string);
    return;
  }
}