TransWikia.com

Is there a better way to avoid repeated 'Len == 1' when interpreting booleans from strings?

Code Review Asked by user227432 on October 27, 2021

My solution to string interpretation is pretty fast. However, I worry about repeated if (Len == 1). That might make the function bigger in the executable. How can I improve my function, to not be as redundant while checking if Len is equal to 1?

#include <ctype.h>
signed char BoolFromStr(const char *const StrIn, register const unsigned char Len) {
    if (!Len || Len > 5 || !StrIn) {
        return -1;
    }
    switch (tolower(*StrIn)) {
        case '0':
            if (Len == 1) {
                return 0;
            }
            break;
        case 'f':
            if (Len == 1 || (Len == 5 && !memcmp(Str+1, (const char[]){'a', 'l', 's', 'e'}, 4))) {
                return 0;
            }
            break;
        case 'n':
            if (Len == 1 || (Len == 2 && Str[1] == 'o')) {
                return 0;
            }
            break;
        case '1':
            if (Len == 1) {
                return 1;
            }
        case 'y':
            if (Len == 1 || (Len == 3 && !memcmp(Str+1, (const char[]){'e', 's'}, 2))) {
                return 1;
            }
            break;
        case 't':
            if (Len == 1 || (Len == 4 && !memcmp(Str+1, (const char[]){'r', 'u', 'e'}, 3))) {
                return 1;
            }
            break;
    }
    return -1;
}

One Answer

How can I improve my function, to not be as redundant while checking if Len is equal to 1?

Make the null character part of the check. Len not needed anywhere.

// if (Len == 1 || (Len == 5 && !memcmp(Str+1, (const char[]){'a', 'l', 's', 'e'}, 4))) {

if (StrIn[1]==0 || !memcmp(Str+1, (const char[]){'a', 'l', 's', 'e', 0}, 5))) {
// or
if (StrIn[1]==0 || 
    (StrIn[1]=='a' && StrIn[2]=='l' && StrIn[3]=='s' && StrIn[4]=='e' && StrIn[5]==0)) {

Bug

BoolFromStr(const char *const StrIn, register const unsigned char Len) is a wrong when the length of the string is say 257 and called as

const char *s = "ttt....ttt"; // 257 t's
BoolFromStr(s, strlen(s)); // reports 1 even though `s` is not `"t"`.

Recommend size_t and drop the register. Do not tie the compilers hands.

BoolFromStr(const char *StrIn, size_t Len);

To reduce size and improve speed I'd consider a hashing of the first byte of StrIn

// Pseudo code

int BoolFromStr(const char *StrIn) {
  const char *tf[] = {"0", "1", "false", "true", "no", "yes", "", "" };
  unsigned hash = hashf(StrIn[0])%8;
  const char *cmps = tf[hash];
  if (StrIn[0] == cmps[0] && (StrIn[1] == 0 || (strcmp(StrIn, cmps) == 0))) {
    return hash & 1;
  }
}

See similar What's the fastest way to interpret a bool string into a number in C?.

Answered by chux - Reinstate Monica on October 27, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP