OpenCores
URL https://opencores.org/ocsvn/riscv_vhdl/riscv_vhdl/trunk

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [common/] [attribute.cpp] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 sergeykhbr
/**
2
 * @file
3
 * @copyright  Copyright 2016 GNSS Sensor Ltd. All right reserved.
4
 * @author     Sergey Khabarov - sergeykhbr@gmail.com
5
 * @brief      Core attribute methods implementation.
6
 */
7
 
8
#include "api_core.h"
9
#include "autobuffer.h"
10
#include "iservice.h"
11
#include "api_utils.h"
12
#include <cstdlib>
13
 
14
namespace debugger {
15
 
16
static const int64_t MIN_ALLOC_BYTES = 1 << 12;
17
static AttributeType NilAttribute;
18
static AutoBuffer strBuffer;
19
 
20
char *attribute_to_string(const AttributeType *attr);
21
const char *string_to_attribute(const char *cfg, AttributeType *out);
22
 
23
void AttributeType::attr_free() {
24
    if (size()) {
25
        if (is_string()) {
26
            RISCV_free(u_.string);
27
        } else if (is_data() && size() > 8) {
28
            RISCV_free(u_.data);
29
        } else if (is_list()) {
30
            for (unsigned i = 0; i < size(); i++) {
31
                u_.list[i].attr_free();
32
            }
33
            RISCV_free(u_.list);
34
        } else if (is_dict()) {
35
            for (unsigned i = 0; i < size(); i++) {
36
                u_.dict[i].key_.attr_free();
37
                u_.dict[i].value_.attr_free();
38
            }
39
            RISCV_free(u_.dict);
40
        }
41
    }
42
    kind_ = Attr_Invalid;
43
    size_ = 0;
44
    u_.integer = 0;
45
}
46
 
47
void AttributeType::clone(const AttributeType *v) {
48
    attr_free();
49
 
50
    if (v->is_string()) {
51
        this->make_string(v->to_string());
52
    } else if (v->is_data()) {
53
        this->make_data(v->size(), v->data());
54
    } else if (v->is_list()) {
55
        make_list(v->size());
56
        for (unsigned i = 0; i < v->size(); i++ ) {
57
            u_.list[i].clone(v->list(i));
58
        }
59
    } else if (v->is_dict()) {
60
        make_dict();
61
        realloc_dict(v->size());
62
        for (unsigned i = 0; i < v->size(); i++ ) {
63
            u_.dict[i].key_.make_string(v->dict_key(i)->to_string());
64
            u_.dict[i].value_.clone(v->dict_value(i));
65
        }
66
    } else {
67
        this->kind_ = v->kind_;
68
        this->u_ = v->u_;
69
        this->size_ = v->size_;
70
    }
71
}
72
 
73
bool AttributeType::is_equal(const char *v) {
74
    if (!is_string()) {
75
        return false;
76
    }
77
    return !strcmp(to_string(), v);
78
}
79
 
80
 
81
AttributeType &AttributeType::operator=(const AttributeType& other) {
82
    if (&other != this) {
83
        clone(&other);
84
    }
85
    return *this;
86
}
87
 
88
 
89
const AttributeType &AttributeType::operator[](unsigned idx) const {
90
    if (is_list()) {
91
        return u_.list[idx];
92
    } else if (is_dict()) {
93
        return u_.dict[idx].value_;
94
    } else {
95
        RISCV_printf(NULL, LOG_ERROR, "%s", "Non-indexed attribute type");
96
    }
97
    return NilAttribute;
98
}
99
 
100
AttributeType &AttributeType::operator[](unsigned idx) {
101
    if (is_list()) {
102
        return u_.list[idx];
103
    } else if (is_dict()) {
104
        return u_.dict[idx].value_;
105
    } else {
106
        RISCV_printf(NULL, LOG_ERROR, "%s", "Non-indexed attribute type");
107
    }
108
    return NilAttribute;
109
}
110
 
111
const AttributeType &AttributeType::operator[](const char *key) const {
112
    for (unsigned i = 0; i < size(); i++) {
113
        if (strcmp(key, u_.dict[i].key_.to_string()) == 0) {
114
            return u_.dict[i].value_;
115
        }
116
    }
117
    AttributeType *pthis = const_cast<AttributeType*>(this);
118
    pthis->realloc_dict(size()+1);
119
    pthis->u_.dict[size()-1].key_.make_string(key);
120
    pthis->u_.dict[size()-1].value_.make_nil();
121
    return u_.dict[size()-1].value_;
122
}
123
 
124
AttributeType &AttributeType::operator[](const char *key) {
125
    for (unsigned i = 0; i < size(); i++) {
126
        if (strcmp(key, u_.dict[i].key_.to_string()) == 0) {
127
            return u_.dict[i].value_;
128
        }
129
    }
130
    realloc_dict(size()+1);
131
    u_.dict[size()-1].key_.make_string(key);
132
    u_.dict[size()-1].value_.make_nil();
133
    return u_.dict[size()-1].value_;
134
}
135
 
136
const uint8_t &AttributeType::operator()(unsigned idx) const {
137
    if (idx > size()) {
138
        RISCV_printf(NULL, LOG_ERROR, "Data index '%d' out of range.", idx);
139
        return u_.data[0];
140
    }
141
    if (size_ > 8) {
142
        return u_.data[idx];
143
    }
144
    return u_.data_bytes[idx];
145
}
146
 
147
void AttributeType::make_string(const char *value) {
148
    attr_free();
149
    if (value) {
150
        kind_ = Attr_String;
151
        size_ = (unsigned)strlen(value);
152
        u_.string = static_cast<char *>(RISCV_malloc(size_ + 1));
153
        memcpy(u_.string, value, size_ + 1);
154
    } else {
155
        kind_ = Attr_Nil;
156
    }
157
}
158
 
159
void AttributeType::make_data(unsigned size) {
160
    attr_free();
161
    kind_ = Attr_Data;
162
    size_ = size;
163
    if (size > 8) {
164
        u_.data = static_cast<uint8_t *>(RISCV_malloc(size_));
165
    }
166
}
167
 
168
void AttributeType::make_data(unsigned size, const void *data) {
169
    attr_free();
170
    kind_ = Attr_Data;
171
    size_ = size;
172
    if (size > 8) {
173
        u_.data = static_cast<uint8_t *>(RISCV_malloc(size_));
174
        memcpy(u_.data, data, size);
175
    } else {
176
        memcpy(u_.data_bytes, data, size);
177
    }
178
}
179
 
180
void AttributeType::make_list(unsigned size) {
181
    attr_free();
182
    kind_ = Attr_List;
183
    if (size) {
184
        realloc_list(size);
185
    }
186
}
187
 
188
void AttributeType::realloc_list(unsigned size) {
189
    size_t req_sz = (size * sizeof(AttributeType) + MIN_ALLOC_BYTES - 1)
190
                   / MIN_ALLOC_BYTES;
191
    size_t cur_sz = (size_ * sizeof(AttributeType) + MIN_ALLOC_BYTES - 1)
192
                  / MIN_ALLOC_BYTES;
193
    if (req_sz > cur_sz ) {
194
        AttributeType * t1 = static_cast<AttributeType *>(
195
                RISCV_malloc(MIN_ALLOC_BYTES * req_sz));
196
        memcpy(t1, u_.list, size_ * sizeof(AttributeType));
197
        memset(&t1[size_], 0,
198
                (MIN_ALLOC_BYTES * req_sz) - size_ * sizeof(AttributeType));
199
        if (size_) {
200
            RISCV_free(u_.list);
201
        }
202
        u_.list = t1;
203
    }
204
    size_ = size;
205
}
206
 
207
void AttributeType::insert_to_list(unsigned idx, const AttributeType *item) {
208
    if (idx > size_) {
209
        RISCV_printf(NULL, LOG_ERROR, "%s", "Insert index out of bound");
210
        return;
211
    }
212
    size_t new_sz = ((size_ + 1) * sizeof(AttributeType) + MIN_ALLOC_BYTES - 1)
213
                  / MIN_ALLOC_BYTES;
214
    AttributeType * t1 = static_cast<AttributeType *>(
215
                RISCV_malloc(MIN_ALLOC_BYTES * new_sz));
216
    memset(t1 + idx, 0, sizeof(AttributeType));  // Fix bug request #4
217
 
218
    memcpy(t1, u_.list, idx * sizeof(AttributeType));
219
    t1[idx].clone(item);
220
    memcpy(&t1[idx + 1], &u_.list[idx], (size_ - idx) * sizeof(AttributeType));
221
    memset(&t1[size_ + 1], 0,
222
          (MIN_ALLOC_BYTES * new_sz) - (size_ + 1) * sizeof(AttributeType));
223
    if (size_) {
224
        RISCV_free(u_.list);
225
    }
226
    u_.list = t1;
227
    size_++;
228
}
229
 
230
void AttributeType::remove_from_list(unsigned idx) {
231
    if (idx >= size_) {
232
        RISCV_printf(NULL, LOG_ERROR, "%s", "Remove index out of range");
233
        return;
234
    }
235
    (*this)[idx].attr_free();
236
    if (idx == (size() - 1)) {
237
        size_ -= 1;
238
    } else if (idx < size ()) {
239
        swap_list_item(idx, size() - 1);
240
        size_ -= 1;
241
    }
242
}
243
 
244
void AttributeType::trim_list(unsigned start, unsigned end) {
245
    for (unsigned i = start; i < (size_ - end); i++) {
246
        u_.list[start + i].attr_free();
247
        u_.list[start + i] = u_.list[end + i];
248
    }
249
    size_ -= (end - start);
250
}
251
 
252
void AttributeType::swap_list_item(unsigned n, unsigned m) {
253
    if (n == m) {
254
        return;
255
    }
256
    unsigned tsize = u_.list[n].size_;
257
    KindType tkind = u_.list[n].kind_;
258
    int64_t tinteger = u_.list[n].u_.integer;
259
    u_.list[n].size_ = u_.list[m].size_;
260
    u_.list[n].kind_ = u_.list[m].kind_;
261
    u_.list[n].u_.integer = u_.list[m].u_.integer;
262
    u_.list[m].size_ = tsize;
263
    u_.list[m].kind_ = tkind;
264
    u_.list[m].u_.integer = tinteger;
265
}
266
 
267
 
268
int partition(AttributeType *A, int lo, int hi, int lst_idx) {
269
    AttributeType *pivot = &(*A)[hi];
270
    bool do_swap;
271
    int i = lo - 1;
272
    for (int j = lo; j < hi; j++) {
273
        AttributeType &item = (*A)[j];
274
        do_swap = false;
275
        if (item.is_string()) {
276
            if (strcmp(item.to_string(), pivot->to_string()) <= 0) {
277
                do_swap = true;
278
            }
279
        } else if (item.is_int64()) {
280
            if (item.to_int64() <= pivot->to_int64()) {
281
                do_swap = true;
282
            }
283
        } else if (item.is_uint64()) {
284
            if (item.to_uint64() <= pivot->to_uint64()) {
285
                do_swap = true;
286
            }
287
        } else if (item.is_list()) {
288
            AttributeType &t1 = item[lst_idx];
289
            if (t1.is_string() &&
290
                strcmp(t1.to_string(), (*pivot)[lst_idx].to_string()) <= 0) {
291
                do_swap = true;
292
            } else if (t1.is_int64() &&
293
                t1.to_int64() <= (*pivot)[lst_idx].to_int64()) {
294
                do_swap = true;
295
            } else if (t1.is_uint64() &&
296
                t1.to_uint64() <= (*pivot)[lst_idx].to_uint64()) {
297
                do_swap = true;
298
            }
299
        } else {
300
            RISCV_printf(NULL, LOG_ERROR, "%s",
301
                        "Not supported attribute type for sorting");
302
            return i + 1;
303
        }
304
 
305
        if (do_swap) {
306
            i = i + 1;
307
            A->swap_list_item(i, j);
308
        }
309
    }
310
    A->swap_list_item(i + 1, hi);
311
    return i + 1;
312
}
313
 
314
void quicksort(AttributeType *A, int lo, int hi, int lst_idx) {
315
    if (lo >= hi) {
316
        return;
317
    }
318
    int p = partition(A, lo, hi, lst_idx);
319
    quicksort(A, lo, p - 1, lst_idx);
320
    quicksort(A, p + 1, hi, lst_idx);
321
}
322
 
323
void AttributeType::sort(int idx) {
324
    if (!is_list()) {
325
        RISCV_printf(NULL, LOG_ERROR, "%s",
326
                    "Sort algorithm can applied only to list attribute");
327
    }
328
    quicksort(this, 0, static_cast<int>(size()) - 1, idx);
329
}
330
 
331
bool AttributeType::has_key(const char *key) const {
332
    for (unsigned i = 0; i < size(); i++) {
333
        if (strcmp(u_.dict[i].key_.to_string(), key) == 0
334
            && !u_.dict[i].value_.is_nil()) {
335
            return true;
336
        }
337
    }
338
    return false;
339
}
340
 
341
const AttributeType *AttributeType::dict_key(unsigned idx) const {
342
    return &u_.dict[idx].key_;
343
}
344
AttributeType *AttributeType::dict_key(unsigned idx) {
345
    return &u_.dict[idx].key_;
346
}
347
 
348
const AttributeType *AttributeType::dict_value(unsigned idx) const {
349
    return &u_.dict[idx].value_;
350
}
351
AttributeType *AttributeType::dict_value(unsigned idx) {
352
    return &u_.dict[idx].value_;
353
}
354
 
355
void AttributeType::make_dict() {
356
    attr_free();
357
    kind_ = Attr_Dict;
358
    size_ = 0;
359
    u_.dict = NULL;
360
}
361
 
362
void AttributeType::realloc_dict(unsigned size) {
363
    size_t req_sz = (size * sizeof(AttributePairType) + MIN_ALLOC_BYTES - 1)
364
                  / MIN_ALLOC_BYTES;
365
    size_t cur_sz = (size_ * sizeof(AttributePairType) + MIN_ALLOC_BYTES - 1)
366
                  / MIN_ALLOC_BYTES;
367
    if (req_sz > cur_sz ) {
368
        AttributePairType * t1 = static_cast<AttributePairType *>(
369
                RISCV_malloc(MIN_ALLOC_BYTES * req_sz));
370
        memcpy(t1, u_.dict, size_ * sizeof(AttributePairType));
371
        memset(&t1[size_], 0,
372
                (MIN_ALLOC_BYTES * req_sz) - size_ * sizeof(AttributePairType));
373
        if (size_) {
374
            RISCV_free(u_.dict);
375
        }
376
        u_.dict = t1;
377
    }
378
    size_ = size;
379
}
380
 
381
char *AttributeType::to_config() {
382
    strBuffer.clear();
383
    attribute_to_string(this);
384
    return strBuffer.getBuffer();
385
}
386
 
387
void AttributeType::from_config(const char *str) {
388
    string_to_attribute(str, this);
389
}
390
 
391
char *attribute_to_string(const AttributeType *attr) {
392
    IService *iserv;
393
    AutoBuffer *buf = &strBuffer;
394
    if (attr->is_nil()) {
395
        buf->write_string("None");
396
    } else if (attr->is_int64() || attr->is_uint64()) {
397
        buf->write_uint64(attr->to_uint64());
398
    } else if (attr->is_string()) {
399
        buf->write_string('\'');
400
        buf->write_string(attr->to_string());
401
        buf->write_string('\'');
402
    } else if (attr->is_bool()) {
403
        if (attr->to_bool()) {
404
            buf->write_string("true");
405
        } else {
406
            buf->write_string("false");
407
        }
408
    } else if (attr->is_list()) {
409
        AttributeType list_item;
410
        unsigned list_sz = attr->size();
411
        buf->write_string('[');
412
        for (unsigned i = 0; i < list_sz; i++) {
413
            list_item = (*attr)[i];
414
            attribute_to_string(&list_item);
415
            if (i < (list_sz - 1)) {
416
                buf->write_string(',');
417
            }
418
        }
419
        buf->write_string(']');
420
    } else if (attr->is_dict()) {
421
        AttributeType dict_item;
422
        unsigned dict_sz = attr->size();;
423
        buf->write_string('{');
424
 
425
        for (unsigned i = 0; i < dict_sz; i++) {
426
            buf->write_string('\'');
427
            buf->write_string(attr->u_.dict[i].key_.to_string());
428
            buf->write_string('\'');
429
            buf->write_string(':');
430
            const AttributeType &dict_value = (*attr)[i];
431
            attribute_to_string(&dict_value);
432
            if (i < (dict_sz - 1)) {
433
                buf->write_string(',');
434
            }
435
        }
436
        buf->write_string('}');
437
    } else if (attr->is_data()) {
438
        buf->write_string('(');
439
        if (attr->size() > 0) {
440
            for (unsigned n = 0; n < attr->size()-1;  n++) {
441
                buf->write_byte((*attr)(n));
442
                buf->write_string(',');
443
            }
444
            buf->write_byte((*attr)(attr->size()-1));
445
        }
446
        buf->write_string(')');
447
    } else if (attr->is_iface()) {
448
        IFace *iface = attr->to_iface();
449
        if (strcmp(iface->getFaceName(), IFACE_SERVICE) == 0) {
450
            iserv = static_cast<IService *>(iface);
451
            buf->write_string('{');
452
            buf->write_string("'Type':'");
453
            buf->write_string(iface->getFaceName());
454
            buf->write_string("','ModuleName':'");
455
            buf->write_string(iserv->getObjName());
456
            buf->write_string("'}");
457
        } else {
458
            RISCV_printf(NULL, LOG_ERROR,
459
                        "Not implemented interface to dict. method");
460
        }
461
    } else if (attr->is_floating()) {
462
        char fstr[64];
463
        RISCV_sprintf(fstr, sizeof(fstr), "%.4f", attr->to_float());
464
        buf->write_string(fstr);
465
    }
466
    return buf->getBuffer();
467
}
468
 
469
const char *skip_special_symbols(const char *cfg) {
470
    const char *pcur = cfg;
471
    while (*pcur == ' ' || *pcur == '\r' || *pcur == '\n' || *pcur == '\t') {
472
        pcur++;
473
    }
474
    return pcur;
475
}
476
 
477
const char *string_to_attribute(const char *cfg,
478
                          AttributeType *out) {
479
    const char *pcur = skip_special_symbols(cfg);
480
 
481
    if (pcur[0] == '\'' || pcur[0] == '"') {
482
        AutoBuffer buf;
483
        uint8_t t1 = pcur[0];
484
        int str_sz = 0;
485
        pcur++;
486
        while (*pcur != t1 && *pcur != '\0') {
487
            pcur++;
488
            str_sz++;
489
        }
490
        buf.write_bin(&cfg[1], str_sz);
491
        pcur++;
492
        out->make_string(buf.getBuffer());
493
    } else if (pcur[0] == '[') {
494
        pcur++;
495
        pcur = skip_special_symbols(pcur);
496
        AttributeType new_item;
497
        out->make_list(0);
498
        while (*pcur != ']' && *pcur != '\0') {
499
            pcur = string_to_attribute(pcur, &new_item);
500
            out->realloc_list(out->size() + 1);
501
            (*out)[out->size() - 1] = new_item;
502
 
503
            pcur = skip_special_symbols(pcur);
504
            if (*pcur == ',') {
505
                pcur++;
506
                pcur = skip_special_symbols(pcur);
507
            }
508
        }
509
        pcur++;
510
        pcur = skip_special_symbols(pcur);
511
    } else if (pcur[0] == '{') {
512
        AttributeType new_key;
513
        AttributeType new_value;
514
        out->make_dict();
515
 
516
        pcur++;
517
        pcur = skip_special_symbols(pcur);
518
        while (*pcur != '}' && *pcur != '\0') {
519
            pcur = string_to_attribute(pcur, &new_key);
520
            pcur = skip_special_symbols(pcur);
521
            if (*pcur == ':') {
522
                pcur++;
523
            }
524
            pcur = skip_special_symbols(pcur);
525
            pcur = string_to_attribute(pcur, &new_value);
526
 
527
            (*out)[new_key.to_string()] = new_value;
528
 
529
            pcur = skip_special_symbols(pcur);
530
            if (*pcur == ',') {
531
                pcur++;
532
                pcur = skip_special_symbols(pcur);
533
            }
534
        }
535
        pcur++;
536
        pcur = skip_special_symbols(pcur);
537
 
538
        if (out->has_key("Type")) {
539
            if (strcmp((*out)["Type"].to_string(), IFACE_SERVICE) == 0) {
540
                IService *iserv;
541
                iserv = static_cast<IService *>(
542
                        RISCV_get_service((*out)["ModuleName"].to_string()));
543
                out->attr_free();
544
                *out = AttributeType(iserv);
545
            } else {
546
                RISCV_printf(NULL, LOG_ERROR,
547
                        "Not implemented string to dict. attribute");
548
            }
549
        }
550
    } else if (pcur[0] == '(') {
551
        AutoBuffer buf;
552
        char byte_value;
553
        pcur++;
554
        pcur = skip_special_symbols(pcur);
555
        while (*pcur != ')' && *pcur != '\0') {
556
            byte_value = 0;
557
            for (int n = 0; n < 2; n++) {
558
                if (*pcur >= 'A' && *pcur <= 'F') {
559
                    byte_value = (byte_value << 4) | ((*pcur - 'A') + 10);
560
                } else {
561
                    byte_value = (byte_value << 4) | (*pcur - '0');
562
                }
563
                pcur++;
564
            }
565
            buf.write_bin(&byte_value, 1);
566
 
567
            pcur = skip_special_symbols(pcur);
568
            if (*pcur == ',') {
569
                pcur++;
570
                pcur = skip_special_symbols(pcur);
571
            }
572
        }
573
        out->make_data(buf.size(), buf.getBuffer());
574
        pcur++;
575
        pcur = skip_special_symbols(pcur);
576
    } else {
577
        pcur = skip_special_symbols(pcur);
578
        if (pcur[0] == 'N' && pcur[1] == 'o' && pcur[2] == 'n'
579
                && pcur[3] == 'e') {
580
            pcur += 4;
581
        } else if (pcur[0] == 'f' && pcur[1] == 'a' && pcur[2] == 'l'
582
                && pcur[3] == 's' && pcur[4] == 'e') {
583
            pcur += 5;
584
            out->make_boolean(false);
585
        } else if (pcur[0] == 't' && pcur[1] == 'r' && pcur[2] == 'u'
586
                && pcur[3] == 'e') {
587
            pcur += 4;
588
            out->make_boolean(true);
589
        } else {
590
            char digits[64] = {0};
591
            int digits_cnt = 0;
592
            if (pcur[0] == '0' && pcur[1] == 'x') {
593
                pcur += 2;
594
                digits[digits_cnt++] = '0';
595
                digits[digits_cnt++] = 'x';
596
            }
597
            while ((*pcur >= '0' && *pcur <= '9')
598
                || (*pcur >= 'a' && *pcur <= 'f')
599
                || (*pcur >= 'A' && *pcur <= 'F')) {
600
                digits[digits_cnt++] = *pcur++;
601
                digits[digits_cnt] = 0;
602
            }
603
            int64_t t1 = strtoull(digits, NULL, 0);
604
            if (pcur[0] == '.') {
605
                digits_cnt = 0;
606
                digits[0] = 0;
607
                double divrate = 1.0;
608
                double d1 = static_cast<double>(t1);
609
                pcur++;
610
                while (*pcur >= '0' && *pcur <= '9') {
611
                    digits[digits_cnt++] = *pcur++;
612
                    digits[digits_cnt] = 0;
613
                    divrate *= 10.0;
614
                }
615
                t1 = strtoull(digits, NULL, 0);
616
                d1 += static_cast<double>(t1)/divrate;
617
                out->make_floating(d1);
618
            } else {
619
                out->make_int64(t1);
620
            }
621
 
622
            /** Guard to skip wrong formatted string and avoid hanging: */
623
            while ((pcur[0] >= 'a' && pcur[0] <= 'z')
624
                || (pcur[0] >= 'A' && pcur[0] <= 'Z')) {
625
                pcur++;
626
            }
627
        }
628
    }
629
    return pcur;
630
}
631
 
632
}  // namespace debugger

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.