1<?php
2/**
3 * This file is part of the FreeDSx ASN1 package.
4 *
5 * (c) Chad Sikorra <Chad.Sikorra@gmail.com>
6 *
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
9 */
10
11namespace FreeDSx\Asn1\Type;
12
13/**
14 * Abstract ASN.1 type.
15 *
16 * @author Chad Sikorra <Chad.Sikorra@gmail.com>
17 */
18abstract class AbstractType implements \Countable, \IteratorAggregate
19{
20    public const TAG_CLASS_UNIVERSAL = 0x00;
21
22    public const TAG_CLASS_CONTEXT_SPECIFIC = 0x80;
23
24    public const TAG_CLASS_APPLICATION = 0x40;
25
26    public const TAG_CLASS_PRIVATE = 0xC0;
27
28    public const TAG_TYPE_BOOLEAN = 0x01;
29
30    public const TAG_TYPE_INTEGER = 0x02;
31
32    public const TAG_TYPE_BIT_STRING = 0x03;
33
34    public const TAG_TYPE_OCTET_STRING = 0x04;
35
36    public const TAG_TYPE_NULL = 0x05;
37
38    public const TAG_TYPE_OID = 0x06;
39
40    public const TAG_TYPE_OBJECT_DESCRIPTOR = 0x07;
41
42    public const TAG_TYPE_EXTERNAL = 0x08;
43
44    public const TAG_TYPE_REAL = 0x09;
45
46    public const TAG_TYPE_ENUMERATED = 0x0A;
47
48    public const TAG_TYPE_EMBEDDED_PDV = 0x0B;
49
50    public const TAG_TYPE_UTF8_STRING = 0x0C;
51
52    public const TAG_TYPE_RELATIVE_OID = 0x0D;
53
54    public const TAG_TYPE_SEQUENCE = 0x10;
55
56    public const TAG_TYPE_SET = 0x11;
57
58    public const TAG_TYPE_NUMERIC_STRING = 0x12;
59
60    public const TAG_TYPE_PRINTABLE_STRING = 0x13;
61
62    public const TAG_TYPE_TELETEX_STRING = 0x14;
63
64    public const TAG_TYPE_VIDEOTEX_STRING = 0x15;
65
66    public const TAG_TYPE_IA5_STRING = 0x16;
67
68    public const TAG_TYPE_UTC_TIME = 0x17;
69
70    public const TAG_TYPE_GENERALIZED_TIME = 0x18;
71
72    public const TAG_TYPE_GRAPHIC_STRING = 0x19;
73
74    public const TAG_TYPE_VISIBLE_STRING = 0x1A;
75
76    public const TAG_TYPE_GENERAL_STRING = 0x1B;
77
78    public const TAG_TYPE_UNIVERSAL_STRING = 0x1C;
79
80    public const TAG_TYPE_CHARACTER_STRING = 0x1D;
81
82    public const TAG_TYPE_BMP_STRING = 0x1E;
83
84    /**
85     * Used in the tag to denote a constructed type.
86     */
87    public const CONSTRUCTED_TYPE = 0x20;
88
89    /**
90     * @var mixed
91     */
92    protected $value;
93
94    /**
95     * @var null|int|string
96     */
97    protected $tagNumber;
98
99    /**
100     * @var int
101     */
102    protected $taggingClass = self::TAG_CLASS_UNIVERSAL;
103
104    /**
105     * @var bool
106     */
107    protected $isConstructed = false;
108
109    /**
110     * @var AbstractType[]
111     */
112    protected $children = [];
113
114    /**
115     * @param mixed $value
116     */
117    public function __construct($value)
118    {
119        $this->value = $value;
120    }
121
122    /**
123     * @return bool
124     */
125    public function getIsConstructed() : bool
126    {
127        return $this->isConstructed;
128    }
129
130    /**
131     * @param bool $isConstructed
132     * @return $this
133     */
134    public function setIsConstructed(bool $isConstructed)
135    {
136        $this->isConstructed = $isConstructed;
137
138        return $this;
139    }
140
141    /**
142     * @param int $taggingClass
143     * @return $this
144     */
145    public function setTagClass(int $taggingClass)
146    {
147        $this->taggingClass = $taggingClass;
148
149        return $this;
150    }
151
152    /**
153     * @return int
154     */
155    public function getTagClass() : int
156    {
157        return $this->taggingClass;
158    }
159
160    /**
161     * @return int|null|string
162     */
163    public function getTagNumber()
164    {
165        return $this->tagNumber;
166    }
167
168    /**
169     * @param int|null|string $int
170     * @return $this
171     */
172    public function setTagNumber($int)
173    {
174        $this->tagNumber = $int;
175
176        return $this;
177    }
178
179    /**
180     * @return mixed
181     */
182    public function getValue()
183    {
184        return $this->value;
185    }
186
187    /**
188     * @param int $index
189     * @return bool
190     */
191    public function hasChild(int $index)
192    {
193        return isset($this->children[$index]);
194    }
195
196    /**
197     * @param AbstractType ...$types
198     * @return $this
199     */
200    public function setChildren(...$types)
201    {
202        $this->children = $types;
203
204        return $this;
205    }
206
207    /**
208     * @return AbstractType[]
209     */
210    public function getChildren() : array
211    {
212        return $this->children;
213    }
214
215    /**
216     * @param int $index
217     * @return null|AbstractType
218     */
219    public function getChild(int $index) : ?AbstractType
220    {
221        return $this->children[$index] ?? null;
222    }
223
224    /**
225     * @param AbstractType ...$types
226     * @return $this
227     */
228    public function addChild(...$types)
229    {
230        foreach ($types as $type) {
231            $this->children[] = $type;
232        }
233
234        return $this;
235    }
236
237    /**
238     * @return int
239     */
240    public function count()
241    {
242        return \count($this->children);
243    }
244
245    /**
246     * @return \ArrayIterator
247     */
248    public function getIterator()
249    {
250        return new \ArrayIterator($this->children);
251    }
252}
253