/*
 * Copyright 2020 Tadashi G. Takaoka
 *
 * 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.
 */

#ifndef __LIBASM_LIST_FORMATTER_H__
#define __LIBASM_LIST_FORMATTER_H__

#include "config_base.h"
#include "str_buffer.h"
#include "value.h"
#include "value_formatter.h"

#include <cstdint>

namespace libasm {
namespace driver {

struct ListFormatter {
    struct Provider {
        virtual const ConfigBase &config() const = 0;
        virtual uint32_t startAddress() const = 0;
        virtual uint8_t bytesSize() const = 0;
        virtual uint8_t getByte(uint8_t offset) const = 0;
    };

    ListFormatter(const Provider &provider);

    void setUpperHex(bool enable);
    /** Switch value, address, bytes formatter radix */
    void setListRadix(Radix radix);

    /**
     * Format |val| as right-justified |width| digits decimal number. Left-justified when |width| is
     * negative.
     */
    void formatDec(StrBuffer &out, uint32_t val, int8_t width = 0);
    /** Format |val| as |width| bits zero-suppressed number */
    void formatValue(StrBuffer &out, uint32_t val, uint8_t bits = 0, int8_t width = 0,
            bool zeroSuppress = false);
    /** Format |addr| as a target address */
    void formatAddress(StrBuffer &out, uint32_t addr);
    uint_fast8_t formatBytes(StrBuffer &out, uint_fast8_t offset);
    constexpr int bytesColumnWidth() const { return 19; }
    /** Format to the next tab position, which is |delta| letters width */
    void formatTab(StrBuffer &out, int tabPosition, int delta = 4);
    void outSpaces(StrBuffer &out, int n);

private:
    const Provider &_provider;
    const ValueFormatter _formatter;
    bool _upperHex;
    Radix _listRadix;

    constexpr int addressColumnWidth() const { return 10; }
    /** Format generated bytes as a target style bytes or words */
    int bytesInLine() const;
};

}  // namespace driver
}  // namespace libasm

#endif

// Local Variables:
// mode: c++
// c-basic-offset: 4
// tab-width: 4
// End:
// vim: set ft=cpp et ts=4 sw=4:
