ed717421f078f268915fdd5a5615e7b8b42f758b
[mirror_edk2.git] / Tools / Source / PcdTools / org / tianocore / pcd / entity / Token.java
1 /** @file
2 Token class.
3
4 This module contains all classes releted to PCD token.
5
6 Copyright (c) 2006, Intel Corporation
7 All rights reserved. This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15 **/
16 package org.tianocore.pcd.entity;
17
18 import java.math.BigInteger;
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23
24 /**
25 This class is to descript a PCD token object. The information of a token mainly
26 comes from MSA, SPD and setting produced by platform developer.
27 **/
28 public class Token {
29 ///
30 /// Enumeration macro defintion for PCD type.
31 ///
32 public static enum PCD_TYPE {FEATURE_FLAG, FIXED_AT_BUILD, PATCHABLE_IN_MODULE, DYNAMIC,
33 DYNAMIC_EX, UNKNOWN}
34
35 ///
36 /// Enumeration macro definition for datum type. All type mainly comes from ProcessBind.h.
37 /// Wizard maybe expand this type as "int, unsigned int, short, unsigned short etc" in
38 /// prompt dialog.
39 ///
40 public static enum DATUM_TYPE {UINT8, UINT16, UINT32, UINT64, BOOLEAN, POINTER, UNKNOWN}
41
42 ///
43 /// Enumeration macor defintion for usage of PCD
44 ///
45 public static enum PCD_USAGE {ALWAYS_PRODUCED, ALWAYS_CONSUMED, SOMETIMES_PRODUCED,
46 SOMETIMES_CONSUMED, UNKNOWN}
47
48 ///
49 /// cName is to identify a PCD entry and will be used for generating autogen.h/autogen.c.
50 /// cName will be defined in MSA, SPD and FPD, can be regarded as primary key with token space guid.
51 ///
52 public String cName;
53
54 ///
55 /// Token space name is the guid defined by token itself in package or module level. This
56 /// name mainly for DynamicEx type. For other PCD type token, his token space name is the
57 /// assignedtokenSpaceName as follows.
58 /// tokenSpaceName is defined in MSA, SPD, FPD, can be regarded as primary key with cName.
59 ///
60 public String tokenSpaceName;
61
62 ///
63 /// tokenNumber is allocated by platform. tokenNumber indicate an index for this token in
64 /// platform token space. For Dynamic, dynamicEx type, this number will be re-adjust by
65 /// PCD run-time database autogen tools.
66 ///
67 public long tokenNumber;
68
69 ///
70 /// This token number is retrieved from FPD file for DynamicEx type.
71 ///
72 public long dynamicExTokenNumber;
73
74 ///
75 /// All supported PCD type, this value can be retrieved from SPD
76 /// Currently, only record all PCD type for this token in FPD file.
77 ///
78 public List<PCD_TYPE> supportedPcdType;
79
80 ///
81 /// If the token's item type is Dynamic or DynamicEx type, isDynamicPCD
82 /// is true.
83 ///
84 public boolean isDynamicPCD;
85
86 ///
87 /// datumSize is to descript the fix size or max size for this token.
88 /// datumSize is defined in SPD.
89 ///
90 public int datumSize;
91
92 ///
93 /// datum type is to descript what type can be expressed by a PCD token.
94 /// For same PCD used in different module, the datum type should be unique.
95 /// So it belong memeber to Token class.
96 ///
97 public DATUM_TYPE datumType;
98
99 ///
100 /// skuData contains all value for SkuNumber of token.
101 /// This field is for Dynamic or DynamicEx type PCD,
102 ///
103 public List<SkuInstance> skuData;
104
105 ///
106 /// consumers array record all module private information who consume this PCD token.
107 ///
108 public Map<String, UsageInstance> consumers;
109
110 /**
111 Constructure function for Token class
112
113 @param cName The name of token
114 @param tokenSpaceName The name of token space, it is a guid string
115 **/
116 public Token(String cName, String tokenSpaceName) {
117 this.cName = cName;
118 this.tokenSpaceName = tokenSpaceName;
119 this.tokenNumber = 0;
120 this.datumType = DATUM_TYPE.UNKNOWN;
121 this.datumSize = -1;
122 this.skuData = new ArrayList<SkuInstance>();
123
124 this.consumers = new HashMap<String, UsageInstance>();
125 this.supportedPcdType = new ArrayList<PCD_TYPE>();
126 }
127
128 /**
129 updateSupportPcdType
130
131 SupportPcdType should be gotten from SPD file actually, but now it just
132 record all PCD type for this token in FPD file.
133
134 @param pcdType new PCD type found in FPD file for this token.
135 **/
136 public void updateSupportPcdType(PCD_TYPE pcdType) {
137 int size = supportedPcdType.size();
138 for (int index = 0; index < size; index++) {
139 if (supportedPcdType.get(index) == pcdType) {
140 return;
141 }
142 }
143
144 //
145 // If not found, add the pcd type to member variable supportedPcdType
146 //
147 supportedPcdType.add(pcdType);
148 }
149
150 /**
151 Judge whether pcdType is belong to dynamic type. Dynamic type includes
152 DYNAMIC and DYNAMIC_EX.
153
154 @param pcdType the judged pcd type
155
156 @return boolean
157 **/
158 public static boolean isDynamic(PCD_TYPE pcdType) {
159 if ((pcdType == PCD_TYPE.DYNAMIC ) ||
160 (pcdType == PCD_TYPE.DYNAMIC_EX)) {
161 return true;
162 }
163
164 return false;
165 }
166
167 /**
168 The pcd type is DynamicEx?
169
170 @retval true Is DynamicEx type
171 @retval false not DynamicEx type
172 **/
173 public boolean isDynamicEx() {
174 int size = supportedPcdType.size();
175 for (int i = 0; i < size; i++) {
176 if (supportedPcdType.get(i) == PCD_TYPE.DYNAMIC_EX) {
177 return true;
178 }
179 }
180
181 return false;
182 }
183
184 /**
185 Use "TokencName + "-" + SpaceTokenName" as primary key when adding token into database
186
187 @param cName Token name.
188 @param tokenSpaceName The token space guid string defined in MSA or SPD
189
190 @retval primary key for this token in token database.
191 **/
192 public static String getPrimaryKeyString(String cName, String tokenSpaceName) {
193 if (tokenSpaceName == null) {
194 return cName + "_nullTokenSpaceGuid";
195 } else {
196 return cName + "_" + tokenSpaceName.toString().replace('-', '_').toLowerCase();
197 }
198 }
199
200 /**
201 If skudata list contains more than one data, then Sku mechanism is enable.
202
203 @retval boolean if the number of sku data exceed to 1
204 **/
205 public boolean isSkuEnable() {
206 if (this.skuData.size() > 1) {
207 return true;
208 }
209 return false;
210 }
211
212 /**
213 If Hii type for value of token
214
215 @return boolean
216 **/
217 public boolean isHiiEnable() {
218 if (getDefaultSku().type == DynamicTokenValue.VALUE_TYPE.HII_TYPE) {
219 return true;
220 }
221 return false;
222 }
223
224 /**
225 If Vpd type for value of token
226
227 @return boolean
228 **/
229 public boolean isVpdEnable() {
230 if (getDefaultSku().type == DynamicTokenValue.VALUE_TYPE.VPD_TYPE) {
231 return true;
232 }
233 return false;
234 }
235
236 /**
237 Get the token primary key in token database.
238
239 @return String
240 **/
241 public String getPrimaryKeyString () {
242 return Token.getPrimaryKeyString(cName, tokenSpaceName);
243 }
244
245 /**
246 Judge datumType is valid
247
248 @param type The datumType want to be judged.
249
250 @retval TRUE - The type is valid.
251 @retval FALSE - The type is invalid.
252 **/
253 public static boolean isValiddatumType(DATUM_TYPE type) {
254 if ((type.ordinal() < DATUM_TYPE.UINT8.ordinal() ) ||
255 (type.ordinal() > DATUM_TYPE.POINTER.ordinal())) {
256 return false;
257 }
258 return true;
259 }
260
261 /**
262 Judge pcdType is valid
263
264 @param type The PCdType want to be judged.
265
266 @retval TRUE - The type is valid.
267 @retval FALSE - The type is invalid.
268 **/
269 public static boolean isValidpcdType(PCD_TYPE type) {
270 if ((type.ordinal() < PCD_TYPE.FEATURE_FLAG.ordinal() ) ||
271 (type.ordinal() > PCD_TYPE.DYNAMIC_EX.ordinal())) {
272 return false;
273 }
274 return true;
275 }
276
277 /**
278 Add an usage instance for token
279
280 @param usageInstance The usage instance
281
282 @retval TRUE - Success to add usage instance.
283 @retval FALSE - Fail to add usage instance
284 **/
285 public boolean addUsageInstance(UsageInstance usageInstance) {
286 if (isUsageInstanceExist(usageInstance.usageId)) {
287 return false;
288 }
289
290 //
291 // Put usage instance into usage instance database of this PCD token.
292 //
293 consumers.put(usageInstance.getPrimaryKey(), usageInstance);
294
295 return true;
296 }
297
298 /**
299 Judge whether exist an usage instance for this token
300
301 @param usageId The UsageInstance identification for usage instance
302
303 @return boolean whether exist an usage instance for this token.
304 **/
305 public boolean isUsageInstanceExist(UsageIdentification usageId) {
306 String keyStr = UsageInstance.getPrimaryKey(usageId);
307
308 return (consumers.get(keyStr) != null);
309 }
310
311 /**
312 Get the PCD_TYPE according to the string of PCD_TYPE
313
314 @param pcdTypeStr The string of PCD_TYPE
315
316 @return PCD_TYPE
317 **/
318 public static PCD_TYPE getPcdTypeFromString(String pcdTypeStr) {
319 if (pcdTypeStr == null) {
320 return PCD_TYPE.UNKNOWN;
321 }
322
323 if (pcdTypeStr.equalsIgnoreCase("FEATURE_FLAG")) {
324 return PCD_TYPE.FEATURE_FLAG;
325 } else if (pcdTypeStr.equalsIgnoreCase("FIXED_AT_BUILD")) {
326 return PCD_TYPE.FIXED_AT_BUILD;
327 } else if (pcdTypeStr.equalsIgnoreCase("PATCHABLE_IN_MODULE")) {
328 return PCD_TYPE.PATCHABLE_IN_MODULE;
329 } else if (pcdTypeStr.equalsIgnoreCase("DYNAMIC")) {
330 return PCD_TYPE.DYNAMIC;
331 } else if (pcdTypeStr.equalsIgnoreCase("DYNAMIC_EX")) {
332 return PCD_TYPE.DYNAMIC_EX;
333 } else {
334 return PCD_TYPE.UNKNOWN;
335 }
336 }
337
338 /**
339 Get the string of given datumType. This string will be used for generating autogen files
340
341 @param datumType Given datumType
342
343 @return The string of datum type.
344 **/
345 public static String getStringOfdatumType(DATUM_TYPE datumType) {
346 return datumType.toString();
347 }
348
349 /**
350 Get the datumType according to a string.
351
352 @param datumTypeStr The string of datumType
353
354 @return DATUM_TYPE
355 **/
356 public static DATUM_TYPE getdatumTypeFromString(String datumTypeStr) {
357 if (datumTypeStr.equalsIgnoreCase("UINT8")) {
358 return DATUM_TYPE.UINT8;
359 } else if (datumTypeStr.equalsIgnoreCase("UINT16")) {
360 return DATUM_TYPE.UINT16;
361 } else if (datumTypeStr.equalsIgnoreCase("UINT32")) {
362 return DATUM_TYPE.UINT32;
363 } else if (datumTypeStr.equalsIgnoreCase("UINT64")) {
364 return DATUM_TYPE.UINT64;
365 } else if (datumTypeStr.equalsIgnoreCase("VOID*")) {
366 return DATUM_TYPE.POINTER;
367 } else if (datumTypeStr.equalsIgnoreCase("BOOLEAN")) {
368 return DATUM_TYPE.BOOLEAN;
369 }
370 return DATUM_TYPE.UNKNOWN;
371 }
372
373 /**
374 Get string of given pcdType
375
376 @param pcdType The given PcdType
377
378 @return The string of PCD_TYPE.
379 **/
380 public static String getStringOfpcdType(PCD_TYPE pcdType) {
381 return pcdType.toString();
382 }
383
384 /**
385 Get the PCD_USAGE according to a string
386
387 @param usageStr The string of PCD_USAGE
388
389 @return The PCD_USAGE
390 **/
391 public static PCD_USAGE getUsageFromString(String usageStr) {
392 if (usageStr == null) {
393 return PCD_USAGE.UNKNOWN;
394 }
395
396 if (usageStr.equalsIgnoreCase("ALWAYS_PRODUCED")) {
397 return PCD_USAGE.ALWAYS_PRODUCED;
398 } else if (usageStr.equalsIgnoreCase("SOMETIMES_PRODUCED")) {
399 return PCD_USAGE.SOMETIMES_PRODUCED;
400 } else if (usageStr.equalsIgnoreCase("ALWAYS_CONSUMED")) {
401 return PCD_USAGE.ALWAYS_CONSUMED;
402 } else if (usageStr.equalsIgnoreCase("SOMETIMES_CONSUMED")) {
403 return PCD_USAGE.SOMETIMES_CONSUMED;
404 }
405
406 return PCD_USAGE.UNKNOWN;
407 }
408
409 /**
410 Get the string of given PCD_USAGE
411
412 @param usage The given PCD_USAGE
413
414 @return The string of PDC_USAGE.
415 **/
416 public static String getStringOfUsage(PCD_USAGE usage) {
417 return usage.toString();
418 }
419
420 /**
421 Get the Defined datumType string for autogen. The string is for generating some MACROs in Autogen.h
422
423 @param datumType The given datumType
424
425 @return string of datum type for autogen.
426 **/
427 public static String GetAutogenDefinedatumTypeString(DATUM_TYPE datumType) {
428 switch (datumType) {
429
430 case UINT8:
431 return "8";
432 case UINT16:
433 return "16";
434 case BOOLEAN:
435 return "BOOL";
436 case POINTER:
437 return "PTR";
438 case UINT32:
439 return "32";
440 case UINT64:
441 return "64";
442 default:
443 return null;
444 }
445 }
446
447 /**
448 Get the datumType String for Autogen. This string will be used for generating defintions of PCD token in autogen
449
450 @param datumType The given datumType
451
452 @return string of datum type.
453 **/
454
455 public static String getAutogendatumTypeString(DATUM_TYPE datumType) {
456 switch (datumType) {
457 case UINT8:
458 return "UINT8";
459 case UINT16:
460 return "UINT16";
461 case UINT32:
462 return "UINT32";
463 case UINT64:
464 return "UINT64";
465 case POINTER:
466 return "VOID*";
467 case BOOLEAN:
468 return "BOOLEAN";
469 }
470 return null;
471 }
472
473 /**
474 Get the datumType string for generating some MACROs in autogen file of Library
475
476 @param datumType The given datumType
477
478 @return String of datum for genrating bit charater.
479 **/
480 public static String getAutogenLibrarydatumTypeString(DATUM_TYPE datumType) {
481 switch (datumType) {
482 case UINT8:
483 return "8";
484 case UINT16:
485 return "16";
486 case BOOLEAN:
487 return "Bool";
488 case POINTER:
489 return "Ptr";
490 case UINT32:
491 return "32";
492 case UINT64:
493 return "64";
494 default:
495 return null;
496 }
497 }
498
499 /**
500 Get the sku data who id is 0.
501
502 @retval DynamicTokenValue the value of this dyanmic token.
503 **/
504 public DynamicTokenValue getDefaultSku() {
505 int index;
506 int size = skuData.size();
507 for (index = 0; index < size; index++) {
508 if (skuData.get(index).id == 0) {
509 return skuData.get(index).value;
510 }
511 }
512
513 return null;
514 }
515
516 /**
517 Get the number of Sku data for this token
518
519 @retval int the number of sku data
520 **/
521 public int getSkuIdCount () {
522 return this.skuData.size();
523 }
524
525 /**
526 Get the size of PCD value, this PCD is POINTER type.
527
528 @param str the string of the value
529 @param al the array list for outer parameter.
530 **/
531 private void getCurrentSizeFromDefaultValue (String str, ArrayList<Integer> al) {
532 if (isValidNullValue(str)) {
533 al.add(new Integer(0));
534 } else {
535 //
536 // isValidNullValue has already make sure that str here
537 // always contain a valid default value of the following 3
538 // cases:
539 // 1) "Hello world" //Assci string
540 // 2) L"Hello" //Unicode string
541 // 3) {0x01, 0x02, 0x03} //Byte stream
542 //
543 if (str.startsWith("\"")) {
544 al.add(new Integer(str.length() - 2));
545 } else if (str.startsWith("L\"")){
546 //
547 // Unicode is 2 bytes each.
548 //
549 al.add(new Integer((str.length() - 3) * 2));
550 } else if (str.startsWith("{")) {
551 //
552 // We count the number of "," in the string.
553 // The number of byte is one plus the number of
554 // comma.
555 //
556 String str2 = str;
557
558 int cnt = 0;
559 int pos = 0;
560 pos = str2.indexOf(",", 0);
561 while (pos != -1) {
562 cnt++;
563 pos++;
564 pos = str2.indexOf(",", pos);
565 }
566 cnt++;
567 al.add(new Integer(cnt));
568 }
569 }
570 }
571
572 /**
573 This method can be used to get the MAX and current size
574 for pointer type dynamic(ex) PCD entry
575 **/
576 public ArrayList<Integer> getPointerTypeSize () {
577 ArrayList<Integer> al = new ArrayList<Integer>();
578
579 //
580 // For VPD_enabled and HII_enabled, we can only return the MAX size.
581 // For the default DATA type dynamic PCD entry, we will return
582 // the MAX size and current size for each SKU_ID.
583 //
584 al.add(new Integer(this.datumSize));
585
586 if (!this.isVpdEnable()) {
587 int idx;
588 if (this.isHiiEnable()){
589 for (idx = 0; idx < this.skuData.size(); idx++) {
590 String str = this.skuData.get(idx).value.hiiDefaultValue;
591 getCurrentSizeFromDefaultValue(str, al);
592 }
593 } else {
594 for (idx = 0; idx < this.skuData.size(); idx++) {
595 String str = this.skuData.get(idx).value.value;
596 getCurrentSizeFromDefaultValue(str, al);
597 }
598 }
599 }
600
601 return al;
602 }
603
604 /**
605 Get default value for a token, For HII type, HiiDefaultValue of default
606 SKU 0 will be returned; For Default type, the defaultvalue of default SKU
607 0 will be returned.
608
609 @return String get the default value for a DYNAMIC type PCD.
610 **/
611 public String getDynamicDefaultValue() {
612 DynamicTokenValue dynamicData = getDefaultSku();
613 if (hasDefaultValue()) {
614 switch (dynamicData.type) {
615 case DEFAULT_TYPE:
616 return dynamicData.value;
617 }
618 }
619
620 return null;
621 }
622
623 /**
624 Judge whether a DYNAMIC PCD has default value.
625
626 @return whether a DYNAMIC PCD has default value.
627 **/
628 public boolean hasDefaultValue () {
629 DynamicTokenValue dynamicValue = null;
630
631 if (isSkuEnable()) {
632 return true;
633 }
634
635 if (this.isDynamicPCD) {
636 dynamicValue = getDefaultSku();
637 switch (dynamicValue.type) {
638 case HII_TYPE:
639 return true;
640 case VPD_TYPE:
641 return true;
642 case DEFAULT_TYPE:
643 return !isValidNullValue(dynamicValue.value);
644 }
645 }
646
647 return false;
648 }
649
650 /**
651 Judge the value is NULL value. NULL value means the value is uninitialized value
652
653 @param judgedValue the want want to be judged
654
655 @return boolean whether the value of PCD is NULL.
656 **/
657 public boolean isValidNullValue(String judgedValue) {
658 String subStr;
659 BigInteger bigIntValue;
660
661 switch (datumType) {
662 case UINT8:
663 case UINT16:
664 case UINT32:
665 if (judgedValue.length() > 2) {
666 if ((judgedValue.charAt(0) == '0') &&
667 ((judgedValue.charAt(1) == 'x') || (judgedValue.charAt(1) == 'X'))){
668 subStr = judgedValue.substring(2, judgedValue.length());
669 bigIntValue = new BigInteger(subStr, 16);
670 } else {
671 bigIntValue = new BigInteger(judgedValue);
672 }
673 } else {
674 bigIntValue = new BigInteger(judgedValue);
675 }
676 if (bigIntValue.bitCount() == 0) {
677 return true;
678 }
679 break;
680 case UINT64:
681 if (judgedValue.length() > 2){
682 if ((judgedValue.charAt(0) == '0') &&
683 ((judgedValue.charAt(1) == 'x') ||
684 (judgedValue.charAt(1) == 'X'))) {
685 bigIntValue = new BigInteger(judgedValue.substring(2, judgedValue.length()), 16);
686 if (bigIntValue.bitCount() == 0) {
687 return true;
688 }
689 } else {
690 bigIntValue = new BigInteger(judgedValue);
691 if (bigIntValue.bitCount() == 0) {
692 return true;
693 }
694 }
695 } else {
696 bigIntValue = new BigInteger(judgedValue);
697 if (bigIntValue.bitCount() == 0) {
698 return true;
699 }
700 }
701 break;
702 case BOOLEAN:
703 if (judgedValue.equalsIgnoreCase("false")) {
704 return true;
705 }
706 break;
707 case POINTER:
708 if (judgedValue.equalsIgnoreCase("\"\"") ||
709 judgedValue.equalsIgnoreCase("L\"\"") ||
710 (judgedValue.length() == 0)) {
711 return true;
712 } else if (judgedValue.trim().charAt(0) == '{') {
713 int start = judgedValue.indexOf('{');
714 int end = judgedValue.lastIndexOf('}');
715 String[] strValueArray = judgedValue.substring(start + 1, end).split(",");
716 if (strValueArray.length > 1) {
717 return false;
718 } else {
719 if (strValueArray[0].matches("(0x)?(0X)?0*")) {
720 return true;
721 }
722 }
723 }
724 }
725 return false;
726 }
727
728 /**
729 Is the string value in Unicode
730
731 @return boolean the string value is UNICODE type string.
732 **/
733 public boolean isHiiDefaultValueUnicodeStringType() {
734 DynamicTokenValue dynamicData = getDefaultSku();
735
736 if (dynamicData == null)
737 return false;
738
739 return dynamicData.hiiDefaultValue.startsWith("L\"")
740 && dynamicData.hiiDefaultValue.endsWith("\"");
741 }
742
743 /**
744 Is the string value in ANSCI
745
746 @return boolean whether the dfault value for HII case is string type.
747 **/
748 public boolean isHiiDefaultValueASCIIStringType() {
749 DynamicTokenValue dynamicData = getDefaultSku();
750
751 if (dynamicData == null)
752 return false;
753
754 return dynamicData.hiiDefaultValue.startsWith("\"")
755 && dynamicData.hiiDefaultValue.endsWith("\"");
756 }
757
758 /**
759 Judege whether current value is UNICODE string type.
760
761 @return boolean whether the value is UNICODE string.
762 **/
763 public boolean isUnicodeStringType () {
764 String str = getDynamicDefaultValue();
765
766 if (str == null) {
767 return false;
768 }
769
770 if (datumType == Token.DATUM_TYPE.POINTER &&
771 str.startsWith("L\"") &&
772 str.endsWith("\"")) {
773 return true;
774 }
775
776 return false;
777 }
778
779 /**
780 Judge whether the string type is ANSIC string.
781
782 @return boolean whether the string type is ANSIC string
783 **/
784 public boolean isASCIIStringType () {
785 String str = getDynamicDefaultValue();
786
787 if (str == null) {
788 return false;
789 }
790
791 if (datumType == Token.DATUM_TYPE.POINTER &&
792 str.startsWith("\"") &&
793 str.endsWith("\"")) {
794 return true;
795 }
796
797 return false;
798 }
799
800 /**
801 Judge whether the string value is byte array.
802
803 @return boolean whether the string value is byte array.
804
805 **/
806 public boolean isByteStreamType () {
807 String str = getDynamicDefaultValue();
808
809 if (str == null) {
810 return false;
811 }
812
813 if (datumType == Token.DATUM_TYPE.POINTER &&
814 str.startsWith("{") &&
815 str.endsWith("}")) {
816 return true;
817 }
818
819 return false;
820
821 }
822
823 /**
824 Get string value for ANSIC string type
825
826 @return String the string value
827 **/
828 public String getStringTypeString () {
829 return getDefaultSku().value.substring(2, getDefaultSku().value.length() - 1);
830 }
831 }
832
833
834
835