/*******************************************************************************
* Copyright 2017-2018 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/

#include "mkldnn_debug.hpp"
#include "reorder/reorder.hpp"

#define DPRINT(...) do { \
    int l = snprintf(buffer, rem_len, __VA_ARGS__); \
    buffer += l; rem_len -= l; \
} while(0)

namespace reorder {

alg_t str2alg(const char *str) {
    if (!strcasecmp("bootstrap", str))
        return ALG_BOOT;
    return ALG_REF;
}

const char *alg2str(alg_t alg) {
    switch (alg) {
    case ALG_REF: return "";
    case ALG_BOOT: return "bootstrap";
    default: assert(!"Invalid algorithm"); return "";
    }
}

dims_t str2dims(const char *str) {
    dims_t dims;
    do {
        int dim, len;
        int scan = sscanf(str, "%d%n", &dim, &len);
        SAFE_V(scan == 1 ? OK : FAIL);
        dims.push_back(dim);
        str += len;
        SAFE_V(*str == 'x' || *str == '\0' ? OK : FAIL);
    } while (*str++ != '\0');
    return dims;
}

void dims2str(const dims_t &dims, char *buffer) {
    int rem_len = max_dims_len;
    for (size_t d = 0; d < dims.size() - 1; ++d)
        DPRINT("%tdx", dims[d]);
    DPRINT("%td", dims[dims.size() - 1]);
}

void prb2str(const prb_t *p, const res_t *res, char *buffer) {
    char dims_buf[max_dims_len] = {0};
    dims2str(p->reorder.dims, dims_buf);

    constexpr int max_alg_len = 20;
    char alg_buf[max_alg_len] = {0};
    const char *algstr = alg2str(p->alg);
    if (algstr && *algstr) {
        int len = snprintf(alg_buf, max_alg_len, "--alg=\"");
        SAFE_V(len >= 0 ? OK : FAIL);
        snprintf(alg_buf + len, max_alg_len - len, "%s", algstr);
        len = (int)strnlen(alg_buf, max_alg_len);
        snprintf(alg_buf + len, max_alg_len - len, "\" ");
    }

    char attr_buf[max_attr_len] = {0};
    bool is_attr_def = p->attr.is_def();
    if (!is_attr_def) {
        int len = snprintf(attr_buf, max_attr_len, "--attr=\"");
        SAFE_V(len >= 0 ? OK : FAIL);
        attr2str(&p->attr, attr_buf + len);
        len = (int)strnlen(attr_buf, max_attr_len);
        snprintf(attr_buf + len, max_attr_len - len, "\" ");
    }

    int rem_len = max_prb_len;
    DPRINT("--idt=%s --odt=%s --ifmt=%s --ofmt=%s %s%s%s",
            dt2str(cfg2dt(p->conf_in)), dt2str(cfg2dt(p->conf_out)),
            fmt2str(p->reorder.fmt_in), fmt2str(p->reorder.fmt_out),
            alg_buf, attr_buf, dims_buf);
}

}
