1 module qrcode.common.qrcodeversion;
2 
3 import qrcode.common.ecblocks;
4 import qrcode.common.errorcorrectionlevel;
5 import qrcode.common.bitmatrix;
6 
7 import std.conv;
8 
9 class QrCodeVersion
10 {
11     ///int[]
12     enum int[] versionDecodeInfo = [
13             0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
14             0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9, 0x177ec,
15             0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75, 0x1f250, 0x209d5,
16             0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64, 0x27541, 0x28c69
17         ];
18 
19     protected int versionNumber, totalCodewords;
20 
21     protected int[] alignmentPatternCenters;
22     protected EcBlocks[] errorCorrectionBlocks;
23 
24     protected static QrCodeVersion[string] versions;
25 
26     this(int vn, int[] aps, EcBlocks[] ecbs)
27     {
28         versionNumber = vn;
29         alignmentPatternCenters = aps;
30         errorCorrectionBlocks = ecbs;
31         totalCodewords = 0;
32         auto ecCodewords = ecbs[0].getEcCodewordsPerBlock();
33         foreach (ecb; ecbs[0].getEcBlocks())
34         {
35             totalCodewords += ecb.count * (ecb.dataCodewords + ecCodewords);
36         }
37     }
38 
39     ///gets the version number.
40     public @property int VersionNumber()
41     {
42         return this.versionNumber;
43     }
44     /**
45 	* Gets the alignment pattern centers.
46 	*
47 	* @return SplFixedArray
48 	*/
49     public @property int[] AlignmentPatternCenters()
50     {
51         return alignmentPatternCenters;
52     }
53 
54     ///Gets the total number of codewords.
55     public @property int TotalCodewords()
56     {
57         return this.totalCodewords;
58     }
59 
60     /**
61 	* Gets the dimension for the current version.
62 	*
63 	* @return integer
64 	*/
65     public @property int DimensionForVersion()
66     {
67         return 17 + 4 * this.versionNumber;
68     }
69 
70     /**
71 	* Gets the number of EC blocks for a specific EC level.
72 	*
73 	* @param  ErrorCorrectionLevel $ecLevel
74 	* @return EcBlocks
75 	*/
76     public EcBlocks getEcBlocksForLevel(ErrorCorrectionLevel ecLevel)
77     {
78         return this.errorCorrectionBlocks[getOrdinalErrorCorrectionLevel(ecLevel)];
79     }
80 
81     /**
82 	* Gets a provisional version number for a specific dimension.
83 	*
84 	* @param  integer $dimension
85 	* @return Version
86 	* @throws Exception\InvalidArgumentException
87 	*/
88     public static QrCodeVersion getProvisionalVersionForDimension(int dimension)
89     {
90         if (dimension % 4 != 1)
91         {
92             throw new Exception("Dimension is not 1 mod 4");
93         }
94         return getVersionForNumber((dimension - 17) >> 2);
95     }
96 
97     /**
98 	* Gets a version instance for a specific version number.
99 	*
100 	* @param  integer $versionNumber
101 	* @return QrCodeVersion
102 	* @throws Exception\InvalidArgumentException
103 	*/
104     public static QrCodeVersion getVersionForNumber(int versionNumber)
105     {
106         if (versionNumber < 1 || versionNumber > 40)
107         {
108             throw new Exception("Version number must be between 1 and 40");
109         }
110         auto p = to!string(versionNumber) in versions;
111         if (p)
112         {
113             return *p;
114         }
115         else
116         {
117             return buildVersion(versionNumber);
118         }
119 
120     }
121 
122     /**
123 	* Build and cache a specific version.
124 	*
125 	* See ISO 18004:2006 6.5.1 Table 9.
126 	*
127 	* @param  integer versionNumber
128 	* @return void
129 	*/
130     protected static QrCodeVersion buildVersion(int versionNumber)
131     {
132         int[] patterns;
133         EcBlocks[] ecBlocks;
134         final switch (versionNumber)
135         {
136         case 1:
137             patterns = [];
138             ecBlocks = [new EcBlocks(7, new EcBlock(1, 19)), new EcBlocks(10,
139                     new EcBlock(1, 16)), new EcBlocks(13, new EcBlock(1, 13)),
140                 new EcBlocks(17, new EcBlock(1, 9)),];
141             break;
142         case 2:
143             patterns = [6, 18];
144             ecBlocks = [new EcBlocks(10, new EcBlock(1, 34)), new EcBlocks(16,
145                     new EcBlock(1, 28)), new EcBlocks(22, new EcBlock(1, 22)),
146                 new EcBlocks(28, new EcBlock(1, 16)),];
147             break;
148         case 3:
149             patterns = [6, 22];
150             ecBlocks = [new EcBlocks(15, new EcBlock(1, 55)), new EcBlocks(26,
151                     new EcBlock(1, 44)), new EcBlocks(18, new EcBlock(2, 17)),
152                 new EcBlocks(22, new EcBlock(2, 13)),];
153             break;
154         case 4:
155             patterns = [6, 26];
156             ecBlocks = [new EcBlocks(20, new EcBlock(1, 80)), new EcBlocks(18,
157                     new EcBlock(2, 32)), new EcBlocks(26, new EcBlock(3, 24)),
158                 new EcBlocks(16, new EcBlock(4, 9)),];
159             break;
160         case 5:
161             patterns = [6, 30];
162             ecBlocks = [new EcBlocks(26, new EcBlock(1, 108)), new EcBlocks(24,
163                     new EcBlock(2, 43)), new EcBlocks(18, new EcBlock(2, 15),
164                     new EcBlock(2, 16)), new EcBlocks(22, new EcBlock(2, 11), new EcBlock(2, 12)),];
165             break;
166         case 6:
167             patterns = [6, 34];
168             ecBlocks = [new EcBlocks(18, new EcBlock(2, 68)), new EcBlocks(16,
169                     new EcBlock(4, 27)), new EcBlocks(24, new EcBlock(4, 19)),
170                 new EcBlocks(28, new EcBlock(4, 15)),];
171             break;
172         case 7:
173             patterns = [6, 22, 38];
174             ecBlocks = [new EcBlocks(20, new EcBlock(2, 78)), new EcBlocks(18,
175                     new EcBlock(4, 31)), new EcBlocks(18, new EcBlock(2, 14),
176                     new EcBlock(4, 15)), new EcBlocks(26, new EcBlock(4, 13)),];
177             break;
178         case 8:
179             patterns = [6, 24, 42];
180             ecBlocks = [new EcBlocks(24, new EcBlock(2, 97)), new EcBlocks(22,
181                     new EcBlock(2, 38), new EcBlock(2, 39)), new EcBlocks(22, new EcBlock(4,
182                     18), new EcBlock(2, 19)), new EcBlocks(26, new EcBlock(4,
183                     14), new EcBlock(2, 15)),];
184             break;
185         case 9:
186             patterns = [6, 26, 46];
187             ecBlocks = [new EcBlocks(30, new EcBlock(2, 116)), new EcBlocks(22,
188                     new EcBlock(3, 36), new EcBlock(2, 37)), new EcBlocks(20, new EcBlock(4,
189                     16), new EcBlock(4, 17)), new EcBlocks(24, new EcBlock(4,
190                     12), new EcBlock(4, 13)),];
191             break;
192         case 10:
193             patterns = [6, 28, 50];
194             ecBlocks = [new EcBlocks(18, new EcBlock(2, 68), new EcBlock(2, 69)),
195                 new EcBlocks(26, new EcBlock(4, 43), new EcBlock(1, 44)), new EcBlocks(24,
196                         new EcBlock(6, 19), new EcBlock(2, 20)), new EcBlocks(28,
197                         new EcBlock(6, 15), new EcBlock(2, 16)),];
198             break;
199         case 11:
200             patterns = [6, 30, 54];
201             ecBlocks = [new EcBlocks(20, new EcBlock(4, 81)), new EcBlocks(30,
202                     new EcBlock(1, 50), new EcBlock(4, 51)), new EcBlocks(28, new EcBlock(4,
203                     22), new EcBlock(4, 23)), new EcBlocks(24, new EcBlock(3,
204                     12), new EcBlock(8, 13)),];
205             break;
206         case 12:
207             patterns = [6, 32, 58];
208             ecBlocks = [new EcBlocks(24, new EcBlock(2, 92), new EcBlock(2, 93)),
209                 new EcBlocks(22, new EcBlock(6, 36), new EcBlock(2, 37)), new EcBlocks(26,
210                         new EcBlock(4, 20), new EcBlock(6, 21)), new EcBlocks(28,
211                         new EcBlock(7, 14), new EcBlock(4, 15)),];
212             break;
213         case 13:
214             patterns = [6, 34, 62];
215             ecBlocks = [new EcBlocks(26, new EcBlock(4, 107)), new EcBlocks(22,
216                     new EcBlock(8, 37), new EcBlock(1, 38)), new EcBlocks(24, new EcBlock(8,
217                     20), new EcBlock(4, 21)), new EcBlocks(22, new EcBlock(12,
218                     11), new EcBlock(4, 12)),];
219             break;
220         case 14:
221             patterns = [6, 26, 46, 66];
222             ecBlocks = [new EcBlocks(30, new EcBlock(3, 115), new EcBlock(1,
223                     116)), new EcBlocks(24, new EcBlock(4, 40), new EcBlock(5,
224                     41)), new EcBlocks(20, new EcBlock(11, 16), new EcBlock(5,
225                     17)), new EcBlocks(24, new EcBlock(11, 12), new EcBlock(5, 13)),];
226             break;
227         case 15:
228             patterns = [6, 26, 48, 70];
229             ecBlocks = [new EcBlocks(22, new EcBlock(5, 87), new EcBlock(1, 88)),
230                 new EcBlocks(24, new EcBlock(5, 41), new EcBlock(5, 42)), new EcBlocks(30,
231                         new EcBlock(5, 24), new EcBlock(7, 25)), new EcBlocks(24,
232                         new EcBlock(11, 12), new EcBlock(7, 13)),];
233             break;
234         case 16:
235             patterns = [6, 26, 50, 74];
236             ecBlocks = [new EcBlocks(24, new EcBlock(5, 98), new EcBlock(1, 99)),
237                 new EcBlocks(28, new EcBlock(7, 45), new EcBlock(3, 46)), new EcBlocks(24,
238                         new EcBlock(15, 19), new EcBlock(2, 20)), new EcBlocks(30,
239                         new EcBlock(3, 15), new EcBlock(13, 16)),];
240             break;
241         case 17:
242             patterns = [6, 30, 54, 78];
243             ecBlocks = [new EcBlocks(28, new EcBlock(1, 107), new EcBlock(5,
244                     108)), new EcBlocks(28, new EcBlock(10, 46), new EcBlock(1,
245                     47)), new EcBlocks(28, new EcBlock(1, 22), new EcBlock(15,
246                     23)), new EcBlocks(28, new EcBlock(2, 14), new EcBlock(17, 15)),];
247             break;
248         case 18:
249             patterns = [6, 30, 56, 82];
250             ecBlocks = [new EcBlocks(30, new EcBlock(5, 120), new EcBlock(1,
251                     121)), new EcBlocks(26, new EcBlock(9, 43), new EcBlock(4,
252                     44)), new EcBlocks(28, new EcBlock(17, 22), new EcBlock(1,
253                     23)), new EcBlocks(28, new EcBlock(2, 14), new EcBlock(19, 15)),];
254             break;
255         case 19:
256             patterns = [6, 30, 58, 86];
257             ecBlocks = [new EcBlocks(28, new EcBlock(3, 113), new EcBlock(4,
258                     114)), new EcBlocks(26, new EcBlock(3, 44), new EcBlock(11,
259                     45)), new EcBlocks(26, new EcBlock(17, 21), new EcBlock(4,
260                     22)), new EcBlocks(26, new EcBlock(9, 13), new EcBlock(16, 14)),];
261             break;
262         case 20:
263             patterns = [6, 34, 62, 90];
264             ecBlocks = [new EcBlocks(28, new EcBlock(3, 107), new EcBlock(5,
265                     108)), new EcBlocks(26, new EcBlock(3, 41), new EcBlock(13,
266                     42)), new EcBlocks(30, new EcBlock(15, 24), new EcBlock(5,
267                     25)), new EcBlocks(28, new EcBlock(15, 15), new EcBlock(10, 16)),];
268             break;
269         case 21:
270             patterns = [6, 28, 50, 72, 94];
271             ecBlocks = [new EcBlocks(28, new EcBlock(4, 116), new EcBlock(4,
272                     117)), new EcBlocks(26, new EcBlock(17, 42)), new EcBlocks(28,
273                     new EcBlock(17, 22), new EcBlock(6, 23)), new EcBlocks(30,
274                     new EcBlock(19, 16), new EcBlock(6, 17)),];
275             break;
276         case 22:
277             patterns = [6, 26, 50, 74, 98];
278             ecBlocks = [new EcBlocks(28, new EcBlock(2, 111), new EcBlock(7,
279                     112)), new EcBlocks(28, new EcBlock(17, 46)), new EcBlocks(30,
280                     new EcBlock(7, 24), new EcBlock(16, 25)), new EcBlocks(24,
281                     new EcBlock(34, 13)),];
282             break;
283         case 23:
284             patterns = [6, 30, 54, 78, 102];
285             ecBlocks = [new EcBlocks(30, new EcBlock(4, 121), new EcBlock(5,
286                     122)), new EcBlocks(28, new EcBlock(4, 47), new EcBlock(14,
287                     48)), new EcBlocks(30, new EcBlock(11, 24), new EcBlock(14,
288                     25)), new EcBlocks(30, new EcBlock(16, 15), new EcBlock(14, 16)),];
289             break;
290         case 24:
291             patterns = [6, 28, 54, 80, 106];
292             ecBlocks = [new EcBlocks(30, new EcBlock(6, 117), new EcBlock(4,
293                     118)), new EcBlocks(28, new EcBlock(6, 45), new EcBlock(14,
294                     46)), new EcBlocks(30, new EcBlock(11, 24), new EcBlock(16,
295                     25)), new EcBlocks(30, new EcBlock(30, 16), new EcBlock(2, 17)),];
296             break;
297         case 25:
298             patterns = [6, 32, 58, 84, 110];
299             ecBlocks = [new EcBlocks(26, new EcBlock(8, 106), new EcBlock(4,
300                     107)), new EcBlocks(28, new EcBlock(8, 47), new EcBlock(13,
301                     48)), new EcBlocks(30, new EcBlock(7, 24), new EcBlock(22,
302                     25)), new EcBlocks(30, new EcBlock(22, 15), new EcBlock(13, 16)),];
303             break;
304         case 26:
305             patterns = [6, 30, 58, 86, 114];
306             ecBlocks = [new EcBlocks(28, new EcBlock(10, 114), new EcBlock(2,
307                     115)), new EcBlocks(28, new EcBlock(19, 46), new EcBlock(4,
308                     47)), new EcBlocks(28, new EcBlock(28, 22), new EcBlock(6,
309                     23)), new EcBlocks(30, new EcBlock(33, 16), new EcBlock(4, 17)),];
310             break;
311         case 27:
312             patterns = [6, 34, 62, 90, 118];
313             ecBlocks = [new EcBlocks(30, new EcBlock(8, 122), new EcBlock(4,
314                     123)), new EcBlocks(28, new EcBlock(22, 45), new EcBlock(3,
315                     46)), new EcBlocks(30, new EcBlock(8, 23), new EcBlock(26,
316                     24)), new EcBlocks(30, new EcBlock(12, 15), new EcBlock(28, 16)),];
317             break;
318         case 28:
319             patterns = [6, 26, 50, 74, 98, 122];
320             ecBlocks = [new EcBlocks(30, new EcBlock(3, 117), new EcBlock(10,
321                     118)), new EcBlocks(28, new EcBlock(3, 45), new EcBlock(23,
322                     46)), new EcBlocks(30, new EcBlock(4, 24), new EcBlock(31,
323                     25)), new EcBlocks(30, new EcBlock(11, 15), new EcBlock(31, 16)),];
324             break;
325         case 29:
326             patterns = [6, 30, 54, 78, 102, 126];
327             ecBlocks = [new EcBlocks(30, new EcBlock(7, 116), new EcBlock(7,
328                     117)), new EcBlocks(28, new EcBlock(21, 45), new EcBlock(7,
329                     46)), new EcBlocks(30, new EcBlock(1, 23), new EcBlock(37,
330                     24)), new EcBlocks(30, new EcBlock(19, 15), new EcBlock(26, 16)),];
331             break;
332         case 30:
333             patterns = [6, 26, 52, 78, 104, 130];
334             ecBlocks = [new EcBlocks(30, new EcBlock(5, 115), new EcBlock(10,
335                     116)), new EcBlocks(28, new EcBlock(19, 47), new EcBlock(10,
336                     48)), new EcBlocks(30, new EcBlock(15, 24), new EcBlock(25,
337                     25)), new EcBlocks(30, new EcBlock(23, 15), new EcBlock(25, 16)),];
338             break;
339         case 31:
340             patterns = [6, 30, 56, 82, 108, 134];
341             ecBlocks = [new EcBlocks(30, new EcBlock(13, 115), new EcBlock(3,
342                     116)), new EcBlocks(28, new EcBlock(2, 46), new EcBlock(29,
343                     47)), new EcBlocks(30, new EcBlock(42, 24), new EcBlock(1,
344                     25)), new EcBlocks(30, new EcBlock(23, 15), new EcBlock(28, 16)),];
345             break;
346         case 32:
347             patterns = [6, 34, 60, 86, 112, 138];
348             ecBlocks = [new EcBlocks(30, new EcBlock(17, 115)), new EcBlocks(28,
349                     new EcBlock(10, 46), new EcBlock(23, 47)), new EcBlocks(30, new EcBlock(10,
350                     24), new EcBlock(35, 25)), new EcBlocks(30, new EcBlock(19,
351                     15), new EcBlock(35, 16)),];
352             break;
353         case 33:
354             patterns = [6, 30, 58, 86, 114, 142];
355             ecBlocks = [new EcBlocks(30, new EcBlock(17, 115), new EcBlock(1,
356                     116)), new EcBlocks(28, new EcBlock(14, 46), new EcBlock(21,
357                     47)), new EcBlocks(30, new EcBlock(29, 24), new EcBlock(19,
358                     25)), new EcBlocks(30, new EcBlock(11, 15), new EcBlock(46, 16)),];
359             break;
360         case 34:
361             patterns = [6, 34, 62, 90, 118, 146];
362             ecBlocks = [new EcBlocks(30, new EcBlock(13, 115), new EcBlock(6,
363                     116)), new EcBlocks(28, new EcBlock(14, 46), new EcBlock(23,
364                     47)), new EcBlocks(30, new EcBlock(44, 24), new EcBlock(7,
365                     25)), new EcBlocks(30, new EcBlock(59, 16), new EcBlock(1, 17)),];
366             break;
367         case 35:
368             patterns = [6, 30, 54, 78, 102, 126, 150];
369             ecBlocks = [new EcBlocks(30, new EcBlock(12, 121), new EcBlock(7,
370                     122)), new EcBlocks(28, new EcBlock(12, 47), new EcBlock(26,
371                     48)), new EcBlocks(30, new EcBlock(39, 24), new EcBlock(14,
372                     25)), new EcBlocks(30, new EcBlock(22, 15), new EcBlock(41, 16)),];
373             break;
374         case 36:
375             patterns = [6, 24, 50, 76, 102, 128, 154];
376             ecBlocks = [new EcBlocks(30, new EcBlock(6, 121), new EcBlock(14,
377                     122)), new EcBlocks(28, new EcBlock(6, 47), new EcBlock(34,
378                     48)), new EcBlocks(30, new EcBlock(46, 24), new EcBlock(10,
379                     25)), new EcBlocks(30, new EcBlock(2, 15), new EcBlock(64, 16)),];
380             break;
381         case 37:
382             patterns = [6, 28, 54, 80, 106, 132, 158];
383             ecBlocks = [new EcBlocks(30, new EcBlock(17, 122), new EcBlock(4,
384                     123)), new EcBlocks(28, new EcBlock(29, 46), new EcBlock(14,
385                     47)), new EcBlocks(30, new EcBlock(49, 24), new EcBlock(10,
386                     25)), new EcBlocks(30, new EcBlock(24, 15), new EcBlock(46, 16)),];
387             break;
388         case 38:
389             patterns = [6, 32, 58, 84, 110, 136, 162];
390             ecBlocks = [new EcBlocks(30, new EcBlock(4, 122), new EcBlock(18,
391                     123)), new EcBlocks(28, new EcBlock(13, 46), new EcBlock(32,
392                     47)), new EcBlocks(30, new EcBlock(48, 24), new EcBlock(14,
393                     25)), new EcBlocks(30, new EcBlock(42, 15), new EcBlock(32, 16)),];
394             break;
395         case 39:
396             patterns = [6, 26, 54, 82, 110, 138, 166];
397             ecBlocks = [new EcBlocks(30, new EcBlock(20, 117), new EcBlock(4,
398                     118)), new EcBlocks(28, new EcBlock(40, 47), new EcBlock(7,
399                     48)), new EcBlocks(30, new EcBlock(43, 24), new EcBlock(22,
400                     25)), new EcBlocks(30, new EcBlock(10, 15), new EcBlock(67, 16)),];
401             break;
402         case 40:
403             patterns = [6, 30, 58, 86, 114, 142, 170];
404             ecBlocks = [new EcBlocks(30, new EcBlock(19, 118), new EcBlock(6,
405                     119)), new EcBlocks(28, new EcBlock(18, 47), new EcBlock(31,
406                     48)), new EcBlocks(30, new EcBlock(34, 24), new EcBlock(34,
407                     25)), new EcBlocks(30, new EcBlock(20, 15), new EcBlock(61, 16)),];
408             break;
409         }
410         auto c = new QrCodeVersion(versionNumber, patterns, ecBlocks);
411         versions[to!string(versionNumber)] = c;
412         return c;
413     }
414 
415     /**
416 	* Decodes version information from an integer and returns the version.
417 	*
418 	* @param  integer $versionBits
419 	* @return Version|null
420 	*/
421     public static QrCodeVersion decodeVersionInformation(int versionBits)
422     {
423         auto bestDifference = int.max;
424         auto bestVersion = 0;
425         foreach (int i, targetVersion; versionDecodeInfo)
426         {
427             if (targetVersion == versionBits)
428             {
429                 return getVersionForNumber(i + 7);
430             }
431             import qrcode.common.formatinformation;
432 
433             auto bitsDifference = FormatInformation.numBitsDiffering(versionBits, targetVersion);
434             if (bitsDifference < bestDifference)
435             {
436                 bestVersion = i + 7;
437                 bestDifference = bitsDifference;
438             }
439         }
440         if (bestDifference <= 3)
441         {
442             return getVersionForNumber(bestVersion);
443         }
444         return null;
445     }
446 
447     /**
448 	* Builds the function pattern for the current version.
449 	*
450 	* @return BitMatrix
451 	*/
452     public BitMatrix buildFunctionPattern()
453     {
454         auto dimension = this.DimensionForVersion;
455         auto bitMatrix = new BitMatrix(dimension);
456         // Top left finder pattern + separator + format
457         bitMatrix.setRegion(0, 0, 9, 9);
458         // Top right finder pattern + separator + format
459         bitMatrix.setRegion(dimension - 8, 0, 8, 9);
460         // Bottom left finder pattern + separator + format
461         bitMatrix.setRegion(0, dimension - 8, 9, 8);
462         // Alignment patterns
463         auto max = this.alignmentPatternCenters.length;
464         for (auto x = 0; x < max; x++)
465         {
466             auto i = this.alignmentPatternCenters[x] - 2;
467             for (auto y = 0; y < max; y++)
468             {
469                 if ((x == 0 && (y == 0 || y == max - 1)) || (x == max - 1 && y == 0))
470                 {
471                     // No alignment patterns near the three finder paterns
472                     continue;
473                 }
474                 bitMatrix.setRegion(this.alignmentPatternCenters[y] - 2, i, 5, 5);
475             }
476         }
477         // Vertical timing pattern
478         bitMatrix.setRegion(6, 9, 1, dimension - 17);
479         // Horizontal timing pattern
480         bitMatrix.setRegion(9, 6, dimension - 17, 1);
481         if (this.versionNumber > 6)
482         {
483             // Version info, top right
484             bitMatrix.setRegion(dimension - 11, 0, 3, 6);
485             // Version info, bottom left
486             bitMatrix.setRegion(0, dimension - 11, 6, 3);
487         }
488         return bitMatrix;
489     }
490 
491     /**
492 	* Returns a string representation for the version.
493 	*
494 	* @return string
495 	*/
496     public override string toString()
497     {
498         import std.conv;
499 
500         return to!string(this.versionNumber);
501     }
502 }