summaryrefslogtreecommitdiff
path: root/Userland/Applications/HexEditor/ValueInspectorModel.h
blob: 27f22f853b58c03ebb33181aba40d7b02fb4fd38 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/*
 * Copyright (c) 2022, Timothy Slater <tslater2006@gmail.com>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#pragma once

#include <AK/DeprecatedString.h>
#include <AK/Hex.h>
#include <AK/NonnullRefPtr.h>
#include <AK/Utf16View.h>
#include <AK/Utf8View.h>
#include <AK/Vector.h>
#include <LibGUI/Model.h>

class ValueInspectorModel final : public GUI::Model {
public:
    enum ValueType {
        SignedByte,
        UnsignedByte,
        SignedShort,
        UnsignedShort,
        SignedInt,
        UnsignedInt,
        SignedLong,
        UnsignedLong,
        Float,
        Double,
        ASCII,
        UTF8,
        UTF16,
        ASCIIString,
        UTF8String,
        UTF16String,
        __Count
    };

    enum Column {
        Type,
        Value
    };

    explicit ValueInspectorModel(bool is_little_endian)
        : m_is_little_endian(is_little_endian)
    {
        for (int i = 0; i < ValueType::__Count; i++)
            set_parsed_value(static_cast<ValueType>(i), "");
    }

    void set_parsed_value(ValueType type, DeprecatedString value)
    {
        m_values[type] = value;
    }

    virtual int row_count(GUI::ModelIndex const& = GUI::ModelIndex()) const override
    {
        return m_values.size();
    }

    virtual int column_count(GUI::ModelIndex const&) const override
    {
        return 2;
    }

    DeprecatedString column_name(int column) const override
    {
        switch (column) {
        case Column::Type:
            return "Type";
        case Column::Value:
            return m_is_little_endian ? "Value (Little Endian)" : "Value (Big Endian)";
        }
        VERIFY_NOT_REACHED();
    }

    DeprecatedString inspector_value_type_to_deprecated_string(ValueType type) const
    {
        switch (type) {
        case SignedByte:
            return "Signed Byte";
        case UnsignedByte:
            return "Unsigned Byte";
        case SignedShort:
            return "Signed Short";
        case UnsignedShort:
            return "Unsigned Short";
        case SignedInt:
            return "Signed Int";
        case UnsignedInt:
            return "Unsigned Int";
        case SignedLong:
            return "Signed Long";
        case UnsignedLong:
            return "Unsigned Long";
        case Float:
            return "Float";
        case Double:
            return "Double";
        case ASCII:
            return "ASCII";
        case UTF8:
            return "UTF-8";
        case UTF16:
            return "UTF-16";
        case ASCIIString:
            return "ASCII String";
        case UTF8String:
            return "UTF-8 String";
        case UTF16String:
            return "UTF-16 String";
        default:
            return "";
        }
    }

    virtual GUI::Variant data(GUI::ModelIndex const& index, GUI::ModelRole role) const override
    {
        if (role == GUI::ModelRole::TextAlignment)
            return Gfx::TextAlignment::CenterLeft;
        if (role == GUI::ModelRole::Display) {
            switch (index.column()) {
            case Column::Type:
                return inspector_value_type_to_deprecated_string(static_cast<ValueType>(index.row()));
            case Column::Value:
                return m_values.at(index.row());
            }
        }
        if (role == GUI::ModelRole::Custom) {
            ValueType selected_type = static_cast<ValueType>(index.row());
            switch (selected_type) {
            case SignedByte:
            case UnsignedByte:
            case ASCII:
                return 1;
            case SignedShort:
            case UnsignedShort:
                return 2;
            case SignedInt:
            case UnsignedInt:
            case Float:
                return 4;
            case SignedLong:
            case UnsignedLong:
            case Double:
                return 8;
            case UTF8: {
                auto utf8_view = Utf8View(m_values.at(index.row()));
                if (utf8_view.validate())
                    return static_cast<i32>(utf8_view.byte_length());
                return 0;
            }
            case UTF16: {
                auto utf16_data = utf8_to_utf16(m_values.at(index.row())).release_value_but_fixme_should_propagate_errors();
                if (Utf16View utf16_view { utf16_data }; utf16_view.validate())
                    return static_cast<i32>(utf16_view.length_in_code_units() * 2);
                return 0;
            }
            default:
                return 0;
            }
        }
        return {};
    }

private:
    bool m_is_little_endian = false;
    Array<DeprecatedString, ValueType::__Count> m_values = {};
};