MOBI_RET mobi_find_attrname(MOBIResult *result, const unsigned char *data_start, const unsigned char *data_end, const char *attrname) {
    if (!result) {
        debug_print("Result structure is null%s", "\n");
        return MOBI_PARAM_ERR;
    }
    result->start = result->end = NULL;
    *(result->value) = '\0';
    if (!data_start || !data_end) {
        debug_print("Data is null%s", "\n");
        return MOBI_PARAM_ERR;
    }
    char needle[MOBI_ATTRNAME_MAXSIZE + 1];
    snprintf(needle, MOBI_ATTRNAME_MAXSIZE + 1, "%s=", attrname);
    size_t needle_length = strlen(needle);
    if (data_start + needle_length > data_end) {
        return MOBI_SUCCESS;
    }
    unsigned char *data = (unsigned char *) data_start;
    const unsigned char quote = '"';
    const unsigned char tag_open = '<';
    const unsigned char tag_close = '>';
    unsigned char last_border = tag_close;
    while (data <= data_end) {
        if (*data == tag_open || *data == tag_close) {
            last_border = *data;
        }
        if (data + needle_length + 2 <= data_end && memcmp(data, needle, needle_length) == 0) {
            /* found match */
            if (last_border != tag_open) {
                /* opening char not found, not an attribute */
                data += needle_length;
                continue;
            }
            /* go to attribute name beginning */
            if (data > data_start) {
                data--;
                if (!isspace(*data) && *data != tag_open) {
                    /* wrong name */
                    data += needle_length;
                    continue;
                }
            }
            result->start = ++data;
            /* now go forward */
            data += needle_length;
            if (*data++ != quote) {
                /* not well formed attribute */
                result->start = NULL;
                continue;
            }
            while (data <= data_end) {
                if (*data == quote) {
                    result->end = ++data;
                    return MOBI_SUCCESS;
                }
                data++;
            }
            result->start = NULL;
        }
        data++;
    }
    return MOBI_SUCCESS;
}
MOBI_RET mobi_find_attrname(MOBIResult *result, const unsigned char *data_start, const unsigned char *data_end, const char *attrname) {
    if (!result) {
        debug_print("Result structure is null%s", "\n");
        return MOBI_PARAM_ERR;
    }
    result->start = result->end = NULL;
    *(result->value) = '\0';
    if (!data_start || !data_end) {
        debug_print("Data is null%s", "\n");
        return MOBI_PARAM_ERR;
    }
    char needle[MOBI_ATTRNAME_MAXSIZE + 1];
    snprintf(needle, MOBI_ATTRNAME_MAXSIZE + 1, "%s=", attrname);
    size_t needle_length = strlen(needle);
    if (data_start + needle_length > data_end) {
        return MOBI_SUCCESS;
    }
    unsigned char *data = (unsigned char *) data_start;
    const unsigned char quote = '"';
    const unsigned char tag_open = '<';
    const unsigned char tag_close = '>';
    unsigned char last_border = tag_close;
    while (data <= data_end) {
        if (*data == tag_open || *data == tag_close) {
            last_border = *data;
        }
        if (data + needle_length + 2 <= data_end && memcmp(data, needle, needle_length) == 0) {
             
            if (last_border != tag_open) {
                 
                data += needle_length;
                continue;
            }
             
            if (data > data_start) {
                data--;
                if (!isspace(*data) && *data != tag_open) {
                     
                    data += needle_length;
                    continue;
                }
            }
            result->start = ++data;
             
            data += needle_length;
            if (*data++ != quote) {
                 
                result->start = NULL;
                continue;
            }
            while (data <= data_end) {
                if (*data == quote) {
                    result->end = ++data;
                    return MOBI_SUCCESS;
                }
                data++;
            }
            result->start = NULL;
        }
        data++;
    }
    return MOBI_SUCCESS;
}