1 ################################################################################
2 #
3 # Copyright (c) 2002-2020 Marcus Holland-Moritz. All rights reserved.
4 # This program is free software; you can redistribute it and/or modify
5 # it under the same terms as Perl itself.
6 #
7 ################################################################################
8 
9 
10 ################################################################################
11 #
12 #   METHOD: member
13 #
14 #   WRITTEN BY: Marcus Holland-Moritz             ON: Jan 2002
15 #   CHANGED BY:                                   ON:
16 #
17 ################################################################################
18 
19 void
20 CBC::member(type, offset = NULL)
21   const char *type
22   SV *offset
23 
24   PREINIT:
25     CBC_METHOD(member);
26     MemberInfo mi;
27     int have_offset, off;
28 
29   PPCODE:
30     off = (have_offset = DEFINED(offset)) ? SvIV(offset) : 0;
31 
32     CT_DEBUG_METHOD2("'%s', %d", type, off);
33 
34     CHECK_PARSE_DATA;
35     CHECK_VOID_CONTEXT;
36 
37     NEED_PARSE_DATA;
38 
39     if (!get_member_info(aTHX_ THIS, type, &mi, 0))
40       Perl_croak(aTHX_ "Cannot find '%s'", type);
41 
42     check_allowed_types(aTHX_ &mi, method, ALLOW_STRUCTS
43                                          | ALLOW_UNIONS
44                                          | ALLOW_ARRAYS);
45 
46     if (mi.flags)
47     {
48       u_32 flags = mi.flags;
49 
50       /* bitfields are not a problem without offset given */
51       if (!have_offset)
52         flags &= ~T_HASBITFIELD;
53 
54       WARN_FLAGS(type, flags);
55     }
56 
57     if (have_offset)
58     {
59       if (off < 0 || off >= (int) mi.size)
60         Perl_croak(aTHX_ "Offset %d out of range (0 <= offset < %d)", off, mi.size);
61 
62       if (GIMME_V == G_ARRAY)
63       {
64         ListIterator li;
65         GMSInfo info;
66         SV     *member;
67         int     count;
68 
69         info.hit = LL_new();
70         info.off = LL_new();
71         info.pad = LL_new();
72 
73         (void) get_member_string(aTHX_ &mi, off, &info);
74 
75         count = LL_count(info.hit)
76               + LL_count(info.off)
77               + LL_count(info.pad);
78 
79         EXTEND(SP, count);
80 
81         LL_foreach(member, li, info.hit)
82           PUSHs(member);
83 
84         LL_foreach(member, li, info.off)
85           PUSHs(member);
86 
87         LL_foreach(member, li, info.pad)
88           PUSHs(member);
89 
90         LL_destroy(info.hit, NULL);
91         LL_destroy(info.off, NULL);
92         LL_destroy(info.pad, NULL);
93 
94         XSRETURN(count);
95       }
96       else
97       {
98         SV *member = get_member_string(aTHX_ &mi, off, NULL);
99         PUSHs(member);
100         XSRETURN(1);
101       }
102     }
103     else
104     {
105       LinkedList list;
106       SV *member;
107       int count;
108 
109       list = GIMME_V == G_ARRAY ? LL_new() : NULL;
110       count = get_all_member_strings(aTHX_ &mi, list);
111 
112       if (GIMME_V == G_ARRAY)
113       {
114         ListIterator li;
115 
116         EXTEND(SP, count);
117 
118         LL_foreach(member, li, list)
119           PUSHs(member);
120 
121         LL_destroy(list, NULL);
122 
123         XSRETURN(count);
124       }
125       else
126         XSRETURN_IV(count);
127     }
128 
129