|
404 | 404 | % overloaded assignment operator: handling assignments at arbitrary depths |
405 | 405 | function obj = subsasgn(obj, idxkey, otherobj) |
406 | 406 | % overloading the setter function, obj.('key').('subkey')=otherobj |
| 407 | + % expanded from rahnema1's sample at https://stackoverflow.com/a/79030223/4271392 |
407 | 408 |
|
408 | 409 | % handle curly bracket indexing for setting attributes |
409 | 410 | oplen = length(idxkey); |
|
422 | 423 | if (iscell(idxkey(oplen).subs) && ~isempty(idxkey(oplen).subs)) |
423 | 424 | attrn = idxkey(oplen).subs{1}; |
424 | 425 | if (ischar(attrn)) |
| 426 | + % Build the path by navigating through keys |
425 | 427 | temppath = obj.currentpath__; |
426 | 428 | for i = 1:oplen - 1 |
427 | 429 | idx = idxkey(i); |
|
441 | 443 | end |
442 | 444 | end |
443 | 445 | end |
| 446 | + % set attribute on original object with computed path |
444 | 447 | obj.setattr(temppath, attrn, otherobj); |
445 | 448 | return |
446 | 449 | end |
|
451 | 454 | if (oplen >= 2 && strcmp(idxkey(oplen).type, '()')) |
452 | 455 | if (strcmp(idxkey(oplen - 1).type, '.') && ischar(idxkey(oplen - 1).subs)) |
453 | 456 | dimname = idxkey(oplen - 1).subs; |
| 457 | + % build path to the data |
454 | 458 | temppath = obj.currentpath__; |
455 | 459 | for i = 1:oplen - 2 |
456 | 460 | idx = idxkey(i); |
|
470 | 474 | end |
471 | 475 | end |
472 | 476 | end |
| 477 | + % check if dimname is in dims |
473 | 478 | dims = obj.getattr(temppath, 'dims'); |
474 | 479 | if (~isempty(dims) && iscell(dims)) |
475 | 480 | dimpos = find(strcmp(dims, dimname)); |
476 | 481 | if (~isempty(dimpos) && ~isempty(idxkey(oplen).subs)) |
| 482 | + % build full indices |
477 | 483 | nddata = length(dims); |
478 | 484 | indices = repmat({':'}, 1, nddata); |
479 | 485 | indices{dimpos(1)} = idxkey(oplen).subs{1}; |
| 486 | + % perform assignment |
480 | 487 | subsargs = struct('type', '()', 'subs', {indices}); |
481 | 488 | if (oplen > 2) |
| 489 | + % need to assign back through the chain |
482 | 490 | subidx = idxkey(1:oplen - 2); |
483 | 491 | tempdata = subsref(obj.data, subidx); |
484 | 492 | tempdata = subsasgn(tempdata, subsargs, otherobj); |
|
495 | 503 | % Fast path: single-level assignment like jd.key = value |
496 | 504 | if (oplen == 1 && strcmp(idxkey(1).type, '.') && ischar(idxkey(1).subs)) |
497 | 505 | fieldname = idxkey(1).subs; |
| 506 | + % Skip if JSONPath |
498 | 507 | if (isempty(fieldname) || fieldname(1) ~= char(36)) |
499 | 508 | if (isempty(obj.data)) |
500 | 509 | obj.data = struct(); |
|
504 | 513 | obj.data.(fieldname) = otherobj; |
505 | 514 | return |
506 | 515 | catch |
| 516 | + % Field name invalid for struct, convert to Map |
507 | 517 | fnames = fieldnames(obj.data); |
508 | 518 | if (~isempty(fnames)) |
509 | 519 | obj.data = containers.Map(fnames, struct2cell(obj.data), 'UniformValues', 0); |
|
594 | 604 | continue |
595 | 605 | end |
596 | 606 | if (ischar(idx.subs) && ~(~isempty(idx.subs) && idx.subs(1) == char(36))) |
| 607 | + % Handle empty or non-struct/map data |
597 | 608 | if isempty(opcell{i}) || (~isstruct(opcell{i}) && ~ismap_(obj.flags__, opcell{i})) |
598 | 609 | opcell{i} = obj.newkey_(); |
599 | 610 | end |
|
0 commit comments