1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is Mozilla Schema Validation.
17 * The Initial Developer of the Original Code is
19 * Portions created by the Initial Developer are Copyright (C) 2004
20 * IBM Corporation. All Rights Reserved.
23 * Doron Rosenberg <doronr@us.ibm.com> (original author)
24 * Laurent Jouanneau <laurent@xulfr.org>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
41 #include "nsStringAPI.h"
42 #include "nsUnicharUtils.h"
44 #include "nsISVSchema.h"
45 #include "nsSchemaValidator.h"
46 #include "nsSchemaValidatorUtils.h"
47 #include "nsISchemaValidatorRegexp.h"
48 #include "nsSchemaDuration.h"
49 #include "nsServiceManagerUtils.h"
61 PRLogModuleInfo
*gSchemaValidationUtilsLog
= PR_NewLogModule("schemaValidation");
63 #define LOG(x) PR_LOG(gSchemaValidationUtilsLog, PR_LOG_DEBUG, x)
64 #define LOG_ENABLED() PR_LOG_TEST(gSchemaValidationUtilsLog, PR_LOG_DEBUG)
70 nsSchemaValidatorUtils::IsValidSchemaInteger(const nsAString
& aNodeValue
,
71 long *aResult
, PRBool aOverFlowCheck
)
73 return !aNodeValue
.IsEmpty() &&
74 IsValidSchemaInteger(NS_ConvertUTF16toUTF8(aNodeValue
).get(),
75 aResult
, aOverFlowCheck
);
78 // overloaded, for char* rather than nsAString
80 nsSchemaValidatorUtils::IsValidSchemaInteger(const char* aString
,
82 PRBool aOverFlowCheck
)
84 PRBool isValid
= PR_FALSE
;
90 long intValue
= strtol(aString
, &pEnd
, 10);
96 isValid
= (!((intValue
== LONG_MAX
|| intValue
== LONG_MIN
) && errno
== ERANGE
))
99 isValid
= (*pEnd
== '\0');
106 nsSchemaValidatorUtils::IsValidSchemaDouble(const nsAString
& aNodeValue
,
109 return !aNodeValue
.IsEmpty() &&
110 IsValidSchemaDouble(NS_ConvertUTF16toUTF8(aNodeValue
).get(), aResult
);
113 // overloaded, for char* rather than nsAString
115 nsSchemaValidatorUtils::IsValidSchemaDouble(const char* aString
,
118 PRBool isValid
= PR_TRUE
;
124 double value
= PR_strtod(aString
, &pEnd
);
126 // If the end pointer desn't point at the end, it wasn't a true double (could
127 // be INF, -INF or NaN though)
129 nsCAutoString
temp(aString
);
131 // doubles may be INF, -INF or NaN
132 if (temp
.EqualsLiteral("INF")) {
134 } else if (temp
.EqualsLiteral("-INF")) {
136 } else if (!temp
.EqualsLiteral("NaN")) {
148 nsSchemaValidatorUtils::ParseDateTime(const nsAString
& aNodeValue
,
149 nsSchemaDateTime
*aResult
)
151 PRBool isValid
= PR_FALSE
;
153 nsAutoString
datetimeString(aNodeValue
);
155 aResult
->date
.isNegative
= (datetimeString
.First() == '-');
158 http://www.w3.org/TR/xmlschema-2/#dateTime
159 (-)CCYY-MM-DDThh:mm:ss(.sss...)
164 // first handle the date part
167 LOG((" Validating DateTime:"));
169 int findString
= datetimeString
.FindChar('T');
172 if (findString
>= 0) {
173 // we get the date part (from 0 to before 'T')
174 isValid
= ParseSchemaDate(Substring(aNodeValue
, 0, findString
), PR_FALSE
, &aResult
->date
);
177 // we get the time part (from after the 'T' till the end)
178 isValid
= ParseSchemaTime(
179 Substring(aNodeValue
, findString
+ 1, aNodeValue
.Length()),
188 nsSchemaValidatorUtils::ParseSchemaDate(const nsAString
& aStrValue
,
189 PRBool aAllowTimeZone
,
192 PRBool isValid
= PR_FALSE
;
195 http://www.w3.org/TR/xmlschema-2/#date
201 const PRUnichar
*start
, *end
, *buffStart
;
202 aStrValue
.BeginReading(&start
, &end
);
203 aStrValue
.BeginReading(&buffStart
);
205 PRUint32 buffLength
= 0;
206 PRBool done
= PR_FALSE
;
207 PRUnichar currentChar
;
212 char timezoneHour
[3] = "";
213 char timezoneMinute
[3] = "";
215 // if year is negative, skip it
216 if (aStrValue
.First() == '-') {
221 while ((start
!= end
) && !done
) {
222 currentChar
= *start
++;
226 if (currentChar
== '-') {
227 if (buffLength
< 4) {
230 year
.Assign(Substring(buffStart
, --start
));
236 // has to be a numerical character or else abort
237 if ((currentChar
> '9') || (currentChar
< '0'))
246 if (buffLength
> 2) {
248 } else if (currentChar
== '-') {
249 if (strcmp(month
, "12") == 1 || buffLength
< 2) {
257 // has to be a numerical character or else abort
258 if ((currentChar
> '9') || (currentChar
< '0'))
261 month
[buffLength
] = currentChar
;
269 if (buffLength
> 2) {
271 } else if (currentChar
== 'Z') {
272 if (aAllowTimeZone
) {
273 if ((start
== end
) && (buffLength
== 2) && (strcmp(day
, "31") < 1)) {
279 } else if ((currentChar
== '+') || (currentChar
== '-')) {
281 if (aAllowTimeZone
) {
286 // no timezones allowed
290 // has to be a numerical character or else abort
291 if ((currentChar
> '9') || (currentChar
< '0'))
294 day
[buffLength
] = currentChar
;
298 // are we at the end?
299 if (start
== end
&& buffLength
== 2) {
309 if (end
-buffStart
== 5) {
310 isValid
= ParseSchemaTimeZone(Substring(buffStart
, end
), timezoneHour
,
323 PRUint32 yearval
= strtoul(NS_ConvertUTF16toUTF8(year
).get(), &pEnd
, 10);
324 if (yearval
== 0 || yearval
== ULONG_MAX
) {
327 PRUint8 monthval
= strtol(month
, &pEnd
, 10);
328 if (monthval
< 1 || monthval
> 12) {
331 PRUint8 dayval
= strtol(day
, &pEnd
, 10);
335 // check for leap years
336 PRUint8 maxDay
= GetMaximumDayInMonthFor(yearval
, monthval
);
337 if (maxDay
>= dayval
) {
338 aDate
->year
= yearval
;
340 // month/day are validated in the parsing code above
341 aDate
->month
= monthval
;
351 LOG((" Date is %s", ((isValid
) ? "Valid" : "Not Valid")));
356 // parses a string as a schema time type and returns the parsed
357 // hour/minute/second/fraction seconds as well as if its a valid
360 nsSchemaValidatorUtils::ParseSchemaTime(const nsAString
& aStrValue
,
363 PRBool isValid
= PR_FALSE
;
365 // time looks like this: HH:MM:SS(.[S]+)(+/-HH:MM)
371 char timezoneHour
[3] = "";
372 char timezoneMinute
[3] = "";
373 // we store the fraction seconds because PR_ExplodeTime seems to skip them.
376 const PRUnichar
*start
, *end
, *buffStart
;
377 aStrValue
.BeginReading(&start
, &end
);
378 aStrValue
.BeginReading(&buffStart
);
380 PRUint32 buffLength
= 0;
381 PRBool done
= PR_FALSE
;
382 PRUnichar currentChar
;
383 PRUnichar tzSign
= PRUnichar(' ');
385 while ((start
!= end
) && !done
) {
386 currentChar
= *start
++;
391 if (buffLength
> 2) {
393 } else if (currentChar
== ':') {
395 if (strcmp(hour
, "24") == 1) {
403 // has to be a numerical character or else abort
404 if ((currentChar
> '9') || (currentChar
< '0'))
407 hour
[buffLength
] = currentChar
;
415 if (buffLength
> 2) {
417 } else if (currentChar
== ':') {
419 if (strcmp(minute
, "59") == 1) {
427 // has to be a numerical character or else abort
428 if ((currentChar
> '9') || (currentChar
< '0'))
431 minute
[buffLength
] = currentChar
;
439 if (buffLength
> 2) {
441 } else if (currentChar
== 'Z') {
442 // if its Z, has to be the last character
443 if ((start
== end
) && (strcmp(second
, "59") != 1)) {
447 tzSign
= currentChar
;
448 } else if ((currentChar
== '+') || (currentChar
== '-')) {
450 if (strcmp(second
, "59") == 1) {
456 tzSign
= currentChar
;
458 } else if (currentChar
== '.') {
459 // fractional seconds exist
460 if (strcmp(second
, "59") == 1) {
468 // has to be a numerical character or else abort
469 if ((currentChar
> '9') || (currentChar
< '0'))
472 second
[buffLength
] = currentChar
;
485 // fractional seconds
487 if (currentChar
== 'Z') {
488 // if its Z, has to be the last character
493 tzSign
= currentChar
;
494 usec
.Assign(Substring(buffStart
, start
- 1));
495 } else if ((currentChar
== '+') || (currentChar
== '-')) {
497 usec
.Assign(Substring(buffStart
, start
- 1));
501 tzSign
= currentChar
;
503 // has to be a numerical character or else abort
504 if ((currentChar
> '9') || (currentChar
< '0'))
506 else if (start
== end
) {
507 usec
.Assign(Substring(buffStart
, end
));
518 if (end
-buffStart
== 5)
519 isValid
= ParseSchemaTimeZone(Substring(buffStart
, end
), timezoneHour
,
531 PRUint32 usecval
= strtoul(NS_ConvertUTF16toUTF8(usec
).get(), &pEnd
, 10);
532 // be carefull, empty usec returns 0
533 if (!usec
.IsEmpty() && (usecval
== 0 || usecval
== ULONG_MAX
)) {
536 aTime
->hour
= strtol(hour
, &pEnd
, 10);
537 aTime
->minute
= strtol(minute
, &pEnd
, 10);
538 aTime
->second
= strtol(second
, &pEnd
, 10);
539 aTime
->millisecond
= usecval
;
542 aTime
->tzIsNegative
= PR_FALSE
;
544 aTime
->tzIsNegative
= PR_TRUE
;
546 aTime
->tzhour
= strtol(timezoneHour
, &pEnd
, 10);
547 aTime
->tzminute
= strtol(timezoneMinute
, &pEnd
, 10);
551 LOG((" Time is %s", ((isValid
) ? "Valid" : "Not Valid")));
557 nsSchemaValidatorUtils::ParseSchemaTimeZone(const nsAString
& aStrValue
,
558 char *rv_tzhour
, char *rv_tzminute
)
560 PRBool isValid
= PR_FALSE
;
561 char timezoneHour
[3] = "";
562 char timezoneMinute
[3] = "";
564 const PRUnichar
*start
, *end
, *buffStart
;
565 aStrValue
.BeginReading(&start
, &end
);
566 aStrValue
.BeginReading(&buffStart
);
568 PRUint32 buffLength
= 0;
569 PRBool done
= PR_FALSE
;
570 PRUnichar currentChar
;
572 LOG(("\n Validating TimeZone"));
574 while ((start
!= end
) && !done
) {
575 currentChar
= *start
++;
580 if (buffLength
> 2) {
582 } else if (currentChar
== ':') {
583 timezoneHour
[2] = '\0';
584 if (strcmp(timezoneHour
, "24") == 1) {
592 // has to be a numerical character or else abort
593 if ((currentChar
> '9') || (currentChar
< '0'))
596 timezoneHour
[buffLength
] = currentChar
;
605 if (buffLength
> 2) {
607 } else if (start
== end
) {
608 if (buffLength
== 1) {
609 if ((currentChar
> '9') || (currentChar
< '0')) {
612 timezoneMinute
[buffLength
] = currentChar
;
614 timezoneMinute
[2] = '\0';
615 if (strcmp(timezoneMinute
, "59") == 1) {
625 // has to be a numerical character or else abort
626 if ((currentChar
> '9') || (currentChar
< '0')) {
629 timezoneMinute
[buffLength
] = currentChar
;
640 strncpy(rv_tzhour
, timezoneHour
, 3);
641 strncpy(rv_tzminute
, timezoneMinute
, 3);
648 -1 - aDateTime1 < aDateTime2
650 1 - aDateTime1 > aDateTime2
653 nsSchemaValidatorUtils::CompareDateTime(nsSchemaDateTime aDateTime1
,
654 nsSchemaDateTime aDateTime2
)
658 nsSchemaDateTime dateTime1
, dateTime2
;
659 AddTimeZoneToDateTime(aDateTime1
, &dateTime1
);
660 AddTimeZoneToDateTime(aDateTime2
, &dateTime2
);
662 if (!dateTime1
.date
.isNegative
&& dateTime2
.date
.isNegative
) {
663 // positive year is always bigger than negative year
665 } else if (dateTime1
.date
.isNegative
&& !dateTime2
.date
.isNegative
) {
668 result
= CompareDate(dateTime1
.date
, dateTime2
.date
);
671 result
= CompareTime(dateTime1
.time
, dateTime2
.time
);
673 if (dateTime1
.date
.isNegative
&& dateTime2
.date
.isNegative
) {
674 // -20 is smaller than -21
677 else if (result
== 1)
686 -1 - aDateTime1 < aDateTime2
688 1 - aDateTime1 > aDateTime2
691 nsSchemaValidatorUtils::CompareDate(nsSchemaDate aDate1
, nsSchemaDate aDate2
)
695 if (aDate1
.year
< aDate2
.year
) {
697 } else if (aDate1
.year
> aDate2
.year
) {
700 if (aDate1
.month
< aDate2
.month
) {
702 } else if (aDate1
.month
> aDate2
.month
) {
705 if (aDate1
.day
< aDate2
.day
) {
707 } else if (aDate1
.day
> aDate2
.day
) {
719 -1 - aDateTime1 < aDateTime2
721 1 - aDateTime1 > aDateTime2
724 nsSchemaValidatorUtils::CompareTime(nsSchemaTime aTime1
, nsSchemaTime aTime2
)
728 if (aTime1
.hour
< aTime2
.hour
) {
730 } else if (aTime1
.hour
> aTime2
.hour
) {
733 if (aTime1
.minute
< aTime2
.minute
) {
735 } else if (aTime1
.minute
> aTime2
.minute
) {
738 if (aTime1
.second
< aTime2
.second
) {
740 } else if (aTime1
.second
> aTime2
.second
) {
743 if (aTime1
.millisecond
< aTime2
.millisecond
) {
745 } else if (aTime1
.millisecond
> aTime2
.millisecond
) {
758 nsSchemaValidatorUtils::AddTimeZoneToDateTime(nsSchemaDateTime aDateTime
,
759 nsSchemaDateTime
* aDestDateTime
)
761 // With timezones, you subtract the timezone difference. So for example,
762 // 2002-10-10T12:00:00+05:00 is 2002-10-10T07:00:00Z
763 PRUint32 year
= aDateTime
.date
.year
;
764 PRUint8 month
= aDateTime
.date
.month
;
765 PRUint8 day
= aDateTime
.date
.day
;
766 int hour
= aDateTime
.time
.hour
;
767 int minute
= aDateTime
.time
.minute
;
768 PRUint8 second
= aDateTime
.time
.second
;
769 PRUint32 millisecond
= aDateTime
.time
.millisecond
;
771 if (aDateTime
.time
.tzIsNegative
) {
772 hour
= hour
+ aDateTime
.time
.tzhour
;
773 minute
= minute
+ aDateTime
.time
.tzminute
;
775 hour
= hour
- aDateTime
.time
.tzhour
;
776 minute
= minute
- aDateTime
.time
.tzminute
;
782 divresult
= div(minute
, 60);
783 hour
+= divresult
.quot
;
784 minute
= divresult
.rem
;
785 } else if (minute
< 0) {
786 minute
= 60 + minute
;
791 if (hour
== 24 && (minute
> 0 || second
> 0)) {
792 // can only be 24:0:0 - need to increment day
795 } else if (hour
> 23) {
796 divresult
= div(hour
, 24);
797 day
+= divresult
.quot
;
798 hour
= divresult
.rem
;
799 } else if (hour
< 0) {
806 // if day is 0, go back a month and make sure we handle month 0 (ie back a year).
814 day
= GetMaximumDayInMonthFor(month
, year
);
816 int maxDay
= GetMaximumDayInMonthFor(month
, year
);
817 while (day
> maxDay
) {
821 // since we are a valid datetime, month has to be 12 before the ++, so will
828 maxDay
= GetMaximumDayInMonthFor(month
, year
);
832 aDestDateTime
->date
.year
= year
;
833 aDestDateTime
->date
.month
= month
;
834 aDestDateTime
->date
.day
= day
;
835 aDestDateTime
->date
.isNegative
= aDateTime
.date
.isNegative
;
836 aDestDateTime
->time
.hour
= hour
;
837 aDestDateTime
->time
.minute
= minute
;
838 aDestDateTime
->time
.second
= second
;
839 aDestDateTime
->time
.millisecond
= millisecond
;
840 aDestDateTime
->time
.tzIsNegative
= aDateTime
.time
.tzIsNegative
;
844 nsSchemaValidatorUtils::GetMonthShorthand(PRUint8 aMonth
, nsACString
& aReturn
)
846 aReturn
.Assign(monthShortHand
[aMonth
- 1].shortHand
);
850 -1 - aYearMonth1 < aYearMonth2
852 1 - aYearMonth1 > aYearMonth2
855 nsSchemaValidatorUtils::CompareGYearMonth(nsSchemaGYearMonth aYearMonth1
,
856 nsSchemaGYearMonth aYearMonth2
)
860 if (aYearMonth1
.gYear
.year
> aYearMonth2
.gYear
.year
) {
862 } else if (aYearMonth1
.gYear
.year
< aYearMonth2
.gYear
.year
) {
865 // both have the same year
866 if (aYearMonth1
.gMonth
.month
> aYearMonth2
.gMonth
.month
)
868 else if (aYearMonth1
.gMonth
.month
< aYearMonth2
.gMonth
.month
)
878 -1 - aMonthDay1 < aMonthDay2
880 1 - aMonthDay1 > aMonthDay2
883 nsSchemaValidatorUtils::CompareGMonthDay(nsSchemaGMonthDay aMonthDay1
,
884 nsSchemaGMonthDay aMonthDay2
)
888 if (aMonthDay1
.gMonth
.month
> aMonthDay2
.gMonth
.month
) {
890 } else if (aMonthDay1
.gMonth
.month
< aMonthDay2
.gMonth
.month
) {
893 // both have the same year
894 if (aMonthDay1
.gDay
.day
> aMonthDay2
.gDay
.day
)
896 else if (aMonthDay1
.gDay
.day
< aMonthDay2
.gDay
.day
)
906 nsSchemaValidatorUtils::ParseSchemaDuration(const nsAString
& aStrValue
,
907 nsISchemaDuration
**aDuration
)
909 PRBool isValid
= PR_FALSE
;
911 const PRUnichar
*start
, *end
, *buffStart
;
912 aStrValue
.BeginReading(&start
, &end
);
913 aStrValue
.BeginReading(&buffStart
);
915 PRUint32 buffLength
= 0;
916 PRBool done
= PR_FALSE
;
917 PRUnichar currentChar
;
919 PRBool isNegative
= PR_FALSE
;
921 // make sure leading P is present. Take negative durations into consideration.
927 isNegative
= PR_TRUE
;
937 nsAutoString parseBuffer
;
938 PRBool timeSeparatorFound
= PR_FALSE
;
940 // designators may not repeat, so keep track of those we find.
941 PRBool yearFound
= PR_FALSE
;
942 PRBool monthFound
= PR_FALSE
;
943 PRBool dayFound
= PR_FALSE
;
944 PRBool hourFound
= PR_FALSE
;
945 PRBool minuteFound
= PR_FALSE
;
946 PRBool secondFound
= PR_FALSE
;
947 PRBool fractionSecondFound
= PR_FALSE
;
955 double fractionSecond
= 0;
957 /* durations look like this:
958 (-)PnYnMnDTnHnMn(.n)S
959 - P is required, plus sign is invalid
960 - order is important, so day after year is invalid (PnDnY)
961 - Y,M,D,H,M,S are called designators
962 - designators are not allowed without a number before them
963 - T is the date/time seperator and is only allowed given a time part
966 while ((start
!= end
) && !done
) {
967 currentChar
= *start
++;
968 // not a number - so it has to be a type designator (YMDTHMS)
969 // it can also be |.| for fractional seconds
970 if ((currentChar
> '9') || (currentChar
< '0')) {
971 // first check if the buffer is bigger than what long can store
972 // which is 11 digits, as we convert to long
973 if ((parseBuffer
.Length() == 10) &&
974 (CompareStrings(parseBuffer
, NS_LITERAL_STRING("2147483647")) == 1)) {
976 } else if (currentChar
== 'Y') {
977 if (yearFound
|| monthFound
|| dayFound
|| timeSeparatorFound
) {
983 } else if (currentChar
== 'M') {
984 // M is used twice - Months and Minutes
985 if (!timeSeparatorFound
)
986 if (monthFound
|| dayFound
|| timeSeparatorFound
) {
990 monthFound
= PR_TRUE
;
993 if (!timeSeparatorFound
) {
996 if (minuteFound
|| secondFound
) {
1000 minuteFound
= PR_TRUE
;
1004 } else if (currentChar
== 'D') {
1005 if (dayFound
|| timeSeparatorFound
) {
1011 } else if (currentChar
== 'T') {
1012 // can't have the time seperator more than once
1013 if (timeSeparatorFound
)
1016 timeSeparatorFound
= PR_TRUE
;
1017 } else if (currentChar
== 'H') {
1018 if (!timeSeparatorFound
|| hourFound
|| secondFound
) {
1022 hourFound
= PR_TRUE
;
1024 } else if (currentChar
== 'S') {
1025 if (!timeSeparatorFound
)
1032 secondFound
= PR_TRUE
;
1034 } else if (currentChar
== '.') {
1035 // fractional seconds
1036 if (fractionSecondFound
) {
1039 parseBuffer
.Append(currentChar
);
1041 fractionSecondFound
= PR_TRUE
;
1047 // if its a designator and no buffer, invalid per spec. Rule doesn't apply
1048 // if T or '.' (fractional seconds), as we need to parse on for those.
1049 // so P200YM is invalid as there is no number before M
1050 if ((currentChar
!= 'T') && (currentChar
!= '.') && (parseBuffer
.Length() == 0)) {
1052 } else if ((currentChar
== 'T') && (start
== end
)) {
1053 // if 'T' is found but no time data after it, invalid
1057 if (!done
&& (currentChar
!= 'T') && (currentChar
!= '.')) {
1062 if (!IsValidSchemaInteger(parseBuffer
, &temp
, PR_TRUE
))
1071 if (!IsValidSchemaInteger(parseBuffer
, &temp
, PR_TRUE
))
1080 if (!IsValidSchemaInteger(parseBuffer
, &temp
, PR_TRUE
))
1089 if (!IsValidSchemaInteger(parseBuffer
, &temp
, PR_TRUE
))
1098 if (!IsValidSchemaInteger(parseBuffer
, &temp
, PR_TRUE
))
1106 // seconds - we have to handle optional fraction seconds as well
1107 if (fractionSecondFound
) {
1108 double temp2
, intpart
;
1110 if (!IsValidSchemaDouble(parseBuffer
, &temp2
)) {
1113 fractionSecond
= modf(temp2
, &intpart
);
1114 second
= static_cast<PRUint32
>(intpart
);
1117 if (!IsValidSchemaInteger(parseBuffer
, &temp
, PR_TRUE
))
1127 // clear buffer unless we are at fraction seconds, since we want to parse
1128 // the seconds and fraction seconds into the same buffer.
1129 if (!fractionSecondFound
) {
1130 parseBuffer
.AssignLiteral("");
1134 if (buffLength
> 11) {
1137 parseBuffer
.Append(currentChar
);
1143 if ((start
== end
) && (!done
)) {
1148 nsISchemaDuration
* duration
= new nsSchemaDuration(year
, month
, day
, hour
,
1153 *aDuration
= duration
;
1154 NS_IF_ADDREF(*aDuration
);
1160 /* compares 2 strings that contain integers.
1161 Schema Integers have no limit, thus converting the strings
1162 into numbers won't work.
1164 -1 - aString1 < aString2
1166 1 - aString1 > aString2
1170 nsSchemaValidatorUtils::CompareStrings(const nsAString
& aString1
,
1171 const nsAString
& aString2
)
1175 PRBool isNegative1
= (aString1
.First() == PRUnichar('-'));
1176 PRBool isNegative2
= (aString2
.First() == PRUnichar('-'));
1178 if (isNegative1
&& !isNegative2
) {
1179 // negative is always smaller than positive
1181 } else if (!isNegative1
&& isNegative2
) {
1182 // positive is always bigger than negative
1186 const PRUnichar
*start1
, *start2
, *end1
, *end2
;
1187 aString1
.BeginReading(&start1
, &end1
);
1188 aString2
.BeginReading(&start2
, &end2
);
1190 // skip negative sign
1197 // jump over leading zeros
1198 PRBool done
= PR_FALSE
;
1199 while ((start1
!= end1
) && !done
) {
1207 while ((start2
!= end2
) && !done
) {
1214 nsAutoString compareString1
, compareString2
;
1215 compareString1
.Assign(Substring(start1
, end1
));
1216 compareString2
.Assign(Substring(start2
, end2
));
1218 // after removing leading 0s, check if they are the same
1219 if (compareString1
.Equals(compareString2
)) {
1223 if (compareString1
.Length() > compareString2
.Length())
1225 else if (compareString1
.Length() < compareString2
.Length())
1228 rv
= strcmp(NS_ConvertUTF16toUTF8(compareString1
).get(),
1229 NS_ConvertUTF16toUTF8(compareString2
).get());
1232 if (isNegative1
&& isNegative2
) {
1241 // For xsd:duration support, the the maximum day for a month/year combo as
1242 // defined in http://w3.org/TR/xmlschema-2/#adding-durations-to-dateTimes.
1244 nsSchemaValidatorUtils::GetMaximumDayInMonthFor(PRUint32 aYearValue
, PRUint8 aMonthValue
)
1246 PRUint8 maxDay
= 28;
1247 PRUint8 month
= ((aMonthValue
- 1) % 12) + 1;
1248 PRUint32 year
= aYearValue
+ ((aMonthValue
- 1) / 12);
1251 Return Value Condition
1252 31 month is either 1, 3, 5, 7, 8, 10, 12
1253 30 month is either 4, 6, 9, 11
1254 29 month is 2 AND either ((year % 4 == 0) AND (year % 100 != 0))
1255 OR (year % 400 == 0)
1259 if ((month
== 1) || (month
== 3) || (month
== 5) || (month
== 7) ||
1260 (month
== 8) || (month
== 10) || (month
== 12))
1262 else if ((month
== 4) || (month
== 6) || (month
== 9) || (month
== 11))
1264 else if ((month
== 2) && (((year
% 4 == 0) && (year
% 100 != 0)) || (year
% 400 == 0)))
1271 * compares 2 durations using the algorithm defined in
1272 * http://w3.org/TR/xmlschema-2/#adding-durations-to-dateTimes by adding them to
1273 * the 4 datetimes specified in http://w3.org/TR/xmlschema-2/#duration-order.
1274 * If not all 4 result in x<y, we return indeterminate per
1275 * http://www.w3.org/TR/xmlschema-2/#facet-comparison-for-durations.
1277 * 0 - aDuration1 < aDuration2
1282 nsSchemaValidatorUtils::CompareDurations(nsISchemaDuration
*aDuration1
,
1283 nsISchemaDuration
*aDuration2
)
1285 int cmp
= 0, tmpcmp
, i
= 0;
1287 nsSchemaDateTime dateTime
, newDateTime1
, newDateTime2
;
1289 char* datetimeArray
[] = { "1696-09-01T00:00:00Z", "1697-02-01T00:00:00Z",
1290 "1903-03-01T00:00:00Z", "1903-07-01T00:00:00Z" };
1291 PRBool indeterminate
= PR_FALSE
;
1293 while (!indeterminate
&& (i
< 4)) {
1294 ParseDateTime(NS_ConvertASCIItoUTF16(datetimeArray
[i
]), &dateTime
);
1296 AddDurationToDatetime(dateTime
, aDuration1
, &newDateTime1
);
1297 AddDurationToDatetime(dateTime
, aDuration2
, &newDateTime2
);
1299 tmpcmp
= CompareDateTime(newDateTime1
, newDateTime2
);
1302 if (tmpcmp
!= cmp
|| tmpcmp
> -1) {
1303 indeterminate
= PR_TRUE
;
1311 return indeterminate
? 1 : 0;
1315 * This method implements the algorithm described at:
1316 * http://w3.org/TR/xmlschema-2/#adding-durations-to-dateTimes
1319 nsSchemaValidatorUtils::AddDurationToDatetime(nsSchemaDateTime aDatetime
,
1320 nsISchemaDuration
*aDuration
,
1321 nsSchemaDateTime
* aResultDateTime
)
1323 // first handle months
1325 aDuration
->GetMonths(&temp
);
1326 temp
+= aDatetime
.date
.month
;
1327 aResultDateTime
->date
.month
= ((temp
- 1) % 12) + 1;
1328 PRInt32 carry
= (temp
- 1) / 12;
1331 aDuration
->GetYears(&temp
);
1332 aResultDateTime
->date
.year
= aDatetime
.date
.year
+ carry
+ temp
;
1338 * XXX: Since the 4 datetimes we add durations to don't have fraction seconds
1339 * we can just add the duration's fraction second (stored as an float),
1340 * which will be < 1.0.
1343 aDuration
->GetFractionSeconds(&dblValue
);
1344 aResultDateTime
->time
.millisecond
= (int) dblValue
* 1000000;
1347 aDuration
->GetSeconds(&temp
);
1348 temp
+= aDatetime
.time
.second
+ carry
;
1349 aResultDateTime
->time
.second
= temp
% 60;
1353 aDuration
->GetMinutes(&temp
);
1354 temp
+= aDatetime
.time
.minute
+ carry
;
1355 aResultDateTime
->time
.minute
= temp
% 60;
1359 aDuration
->GetHours(&temp
);
1360 temp
+= aDatetime
.time
.hour
+ carry
;
1361 aResultDateTime
->time
.hour
= temp
% 24;
1365 int maxDay
= GetMaximumDayInMonthFor(aResultDateTime
->date
.year
,
1366 aResultDateTime
->date
.month
);
1368 if (aDatetime
.date
.day
> maxDay
)
1370 else if (aDatetime
.date
.day
< 1)
1373 tempDays
= aDatetime
.date
.day
;
1375 aDuration
->GetDays(&temp
);
1376 aResultDateTime
->date
.day
= tempDays
+ carry
+ temp
;
1378 PRBool done
= PR_FALSE
;
1380 maxDay
= GetMaximumDayInMonthFor(aResultDateTime
->date
.year
,
1381 aResultDateTime
->date
.month
);
1382 if (aResultDateTime
->date
.day
< 1) {
1383 aResultDateTime
->date
.day
+=
1384 GetMaximumDayInMonthFor(aResultDateTime
->date
.year
,
1385 aResultDateTime
->date
.month
- 1);
1387 } else if (aResultDateTime
->date
.day
> maxDay
) {
1388 aResultDateTime
->date
.day
-= maxDay
;
1395 temp
= aResultDateTime
->date
.month
+ carry
;
1396 aResultDateTime
->date
.month
= ((temp
- 1) % 12) + 1;
1397 aResultDateTime
->date
.year
+= (temp
- 1) / 12;
1401 // copy over negative and tz data
1402 aResultDateTime
->date
.isNegative
= aDatetime
.date
.isNegative
;
1404 aResultDateTime
->time
.tzIsNegative
= aDatetime
.time
.tzIsNegative
;
1405 aResultDateTime
->time
.tzhour
= aDatetime
.time
.tzhour
;
1406 aResultDateTime
->time
.tzminute
= aDatetime
.time
.tzminute
;
1408 LOG(("\n New datetime is %d-%d-%d %d:%d:%d\n", aResultDateTime
->date
.day
,
1409 aResultDateTime
->date
.month
, aResultDateTime
->date
.year
,
1410 aResultDateTime
->time
.hour
, aResultDateTime
->time
.minute
,
1411 aResultDateTime
->time
.second
));
1414 // http://www.w3.org/TR/xmlschema-2/#normalizedString
1416 nsSchemaValidatorUtils::IsValidSchemaNormalizedString(const nsAString
&aStrValue
)
1418 PRBool isValid
= PR_FALSE
;
1419 nsAutoString
string(aStrValue
);
1421 // may not contain carriage return, line feed nor tab characters
1422 if (FindCharInSet(string
, "\t\r\n") == kNotFound
)
1427 // http://www.w3.org/TR/xmlschema-2/#token
1429 nsSchemaValidatorUtils::IsValidSchemaToken(const nsAString
&aStrValue
)
1431 PRBool isValid
= PR_FALSE
;
1432 nsAutoString
string(aStrValue
);
1434 // may not contain carriage return, line feed, tab characters. Also can
1435 // not contain leading/trailing whitespace and no internal sequences of
1436 // two or more spaces.
1437 if ((FindCharInSet(string
, "\t\r\n") == kNotFound
) &&
1438 (string
.Find(NS_LITERAL_STRING(" ")) == kNotFound
) &&
1439 (string
.First() != ' ') &&
1440 (string
.CharAt(string
.Length() - 1) != ' '))
1446 // http://www.w3.org/TR/xmlschema-2/#language
1448 nsSchemaValidatorUtils::IsValidSchemaLanguage(const nsAString
&aStrValue
)
1450 PRBool isValid
= PR_FALSE
;
1452 // pattern is defined in spec
1453 nsAutoString pattern
;
1454 pattern
.AssignLiteral("[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*");
1456 nsCOMPtr
<nsISchemaValidatorRegexp
> regexp
= do_GetService(kREGEXP_CID
);
1457 nsresult rv
= regexp
->RunRegexp(aStrValue
, pattern
, "g", &isValid
);
1458 NS_ENSURE_SUCCESS(rv
, rv
);
1463 // http://www.w3.org/TR/xmlschema-2/#name
1465 nsSchemaValidatorUtils::IsValidSchemaName(const nsAString
&aStrValue
)
1467 PRBool isValid
= PR_FALSE
;
1469 // xsd:Name is restriction on xsd:token
1470 if (IsValidSchemaToken(aStrValue
)) {
1471 /* http://www.w3.org/TR/2000/WD-xml-2e-20000814
1472 [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
1473 CombiningChar | Extender
1474 [5] Name ::= (Letter | '_' | ':') ( NameChar)*
1476 // XXX Need to handling CombiningChar and Extender as well
1477 // XXX Additional Unicode testing needed?
1478 nsAutoString pattern
;
1479 pattern
.AssignLiteral("^[a-zA-Z_:][\\w\\.\\-:]*$");
1480 nsCOMPtr
<nsISchemaValidatorRegexp
> regexp
= do_GetService(kREGEXP_CID
);
1481 nsresult rv
= regexp
->RunRegexp(aStrValue
, pattern
, "g", &isValid
);
1482 NS_ENSURE_SUCCESS(rv
, rv
);
1488 // http://www.w3.org/TR/xmlschema-2/#ncname
1490 nsSchemaValidatorUtils::IsValidSchemaNCName(const nsAString
&aStrValue
)
1492 PRBool isValid
= PR_FALSE
;
1494 // xsd:NCNAME is a restriction on xsd:Name
1495 if (IsValidSchemaToken(aStrValue
)) {
1496 /* http://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-NCName
1497 NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
1498 CombiningChar | Extender
1499 NCName ::= (Letter | '_') (NCNameChar)*
1501 nsAutoString pattern
;
1502 // XXX Need to handle Combining|Extender and Unicode Letters
1503 // xsd:Name minus the ":"
1504 pattern
.AssignLiteral("^[a-zA-Z_][\\w\\.\\-]*$");
1505 nsCOMPtr
<nsISchemaValidatorRegexp
> regexp
= do_GetService(kREGEXP_CID
);
1506 nsresult rv
= regexp
->RunRegexp(aStrValue
, pattern
, "g", &isValid
);
1507 NS_ENSURE_SUCCESS(rv
, rv
);
1513 // http://www.w3.org/TR/xmlschema-2/#id
1515 nsSchemaValidatorUtils::IsValidSchemaID(const nsAString
&aStrValue
)
1517 PRBool isValid
= PR_FALSE
;
1519 // xsd:ID is a restriction of xsd:NCNAME
1520 if (IsValidSchemaNCName(aStrValue
)) {
1522 // XXX Uniqueness tests per
1523 // http://www.w3.org/TR/2000/WD-xml-2e-20000814#NT-TokenizedType
1529 // http://www.w3.org/TR/xmlschema-2/#idref
1531 nsSchemaValidatorUtils::IsValidSchemaIDRef(const nsAString
&aStrValue
)
1533 PRBool isValid
= PR_FALSE
;
1535 // xsd:IDREF is a restriction of xsd:NCName
1536 if (IsValidSchemaNCName(aStrValue
)) {
1538 // XXX Ensure IDREF really references an ID,
1539 // http://www.w3.org/TR/2000/WD-xml-2e-20000814#idref
1545 // http://www.w3.org/TR/xmlschema-2/#idrefs
1547 nsSchemaValidatorUtils::IsValidSchemaIDRefs(const nsAString
&aStrValue
)
1549 PRBool isValid
= PR_FALSE
;
1551 // Need to validate each IDREF
1552 const PRUnichar
*iter
, *end
, *tokenStart
;
1554 aStrValue
.BeginReading(&iter
, &end
);
1555 aStrValue
.BeginReading(&tokenStart
);
1556 while (iter
!= end
) {
1557 for (;IsWhitespace(*iter
) && iter
!= end
; ++iter
);
1560 // Find end of token
1561 for (;!IsWhitespace(*iter
) && iter
!= end
; ++iter
);
1563 // Get the token/idref and validate
1564 idref
= Substring(tokenStart
, iter
);
1565 isValid
= IsValidSchemaIDRef(idref
);
1566 if (!isValid
) break; // No need to continue
1568 if (iter
!= end
) ++iter
;
1575 nsSchemaValidatorUtils::IsWhitespace(PRUnichar aChar
)
1577 return aChar
== ' ' || aChar
== '\t' || aChar
== '\n' ||
1578 aChar
== '\r' || aChar
== '\v';
1581 // http://www.w3.org/TR/xmlschema-2/#nmtoken
1583 nsSchemaValidatorUtils::IsValidSchemaNMToken(const nsAString
&aStrValue
)
1585 PRBool isValid
= PR_FALSE
;
1587 // xsd:NMTOKEN is a restriction on xsd:token
1588 if (IsValidSchemaToken(aStrValue
)) {
1590 NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
1591 CombiningChar | Extender
1592 Nmtoken ::= (NameChar)+
1594 nsAutoString pattern
;
1595 // XXX Need to handle Combining|Extender and possibly unicode letters
1596 pattern
.AssignLiteral("^[\\w\\.\\-_:]*$");
1597 nsCOMPtr
<nsISchemaValidatorRegexp
> regexp
= do_GetService(kREGEXP_CID
);
1598 nsresult rv
= regexp
->RunRegexp(aStrValue
, pattern
, "g", &isValid
);
1599 NS_ENSURE_SUCCESS(rv
, rv
);
1605 // http://www.w3.org/TR/xmlschema-2/#nmtokens
1607 nsSchemaValidatorUtils::IsValidSchemaNMTokens(const nsAString
&aStrValue
)
1609 PRBool isValid
= PR_FALSE
;
1611 // Need to validate each NNTOKEN
1612 const PRUnichar
*iter
, *end
, *tokenStart
;
1614 aStrValue
.BeginReading(&iter
, &end
);
1615 aStrValue
.BeginReading(&tokenStart
);
1616 while (iter
!= end
) {
1617 for (;IsWhitespace(*iter
) && iter
!= end
; ++iter
);
1620 // Find end of token
1621 for (;!IsWhitespace(*iter
) && iter
!= end
; ++iter
);
1623 // Get the token/idref and validate
1624 idref
= Substring(tokenStart
, iter
);
1625 isValid
= IsValidSchemaNMToken(idref
);
1626 if (!isValid
) break; // No need to continue
1628 if (iter
!= end
) ++iter
;
1635 nsSchemaValidatorUtils::HandleEnumeration(const nsAString
&aStrValue
,
1636 const nsStringArray
&aEnumerationList
)
1638 PRBool isValid
= PR_FALSE
;
1640 // check enumeration
1641 PRInt32 count
= aEnumerationList
.Count();
1642 for (PRInt32 i
= 0; i
< count
; ++i
) {
1643 if (aEnumerationList
[i
]->Equals(aStrValue
)) {
1645 LOG((" Valid: Value matched enumeration #%d", i
));
1651 LOG((" Not valid: Value doesn't match any of the enumerations"));
1658 nsSchemaValidatorUtils::RemoveLeadingZeros(nsAString
& aString
)
1660 const PRUnichar
*start
, *end
;
1661 aString
.BeginReading(&start
, &end
);
1663 PRBool done
= PR_FALSE
;
1664 PRUint32 count
= 0, indexstart
= 0;
1666 if (*start
== '+' || *start
== '-') {
1671 while ((start
!= end
) && !done
)
1673 if (*start
++ == '0') {
1680 PRUint32 length
= aString
.Length() - indexstart
;
1682 // if the entire string is composed of zeros, set it to one zero
1683 if (length
== count
) {
1684 aString
.AssignLiteral("0");
1686 // finally, remove the leading zeros
1687 aString
.Cut(indexstart
, count
);
1692 nsSchemaValidatorUtils::RemoveTrailingZeros(nsAString
& aString
)
1694 const PRUnichar
*start
, *end
;
1695 aString
.BeginReading(&start
, &end
);
1697 PRUint32 length
= aString
.Length();
1699 PRBool done
= PR_FALSE
;
1704 while ((start
!= end
) && !done
)
1706 if (*end
-- == '0') {
1713 // finally, remove the trailing zeros
1714 aString
.Cut(length
- count
, count
);
1717 // Walks the inheritance tree until it finds a type that isn't a restriction
1718 // type. While it finds restriction types, it collects restriction facets and
1719 // places them into the nsSchemaDerivedSimpleType. Once a facet has been found,
1720 // it makes sure that it won't be overwritten by the same facet defined in one
1721 // of the inherited types.
1723 nsSchemaValidatorUtils::GetDerivedSimpleType(nsISVSchemaSimpleType
*aSimpleType
,
1724 nsSchemaDerivedSimpleType
*aDerived
)
1726 PRBool done
= PR_FALSE
, hasEnumerations
= PR_FALSE
;
1727 nsCOMPtr
<nsISVSchemaSimpleType
> simpleType(aSimpleType
);
1728 PRUint16 simpleTypeValue
;
1729 PRUint32 facetCount
;
1731 nsAutoString enumeration
;
1732 nsresult rv
= NS_OK
;
1734 while(simpleType
&& !done
) {
1735 // get the type of the simpletype
1736 rv
= simpleType
->GetSimpleType(&simpleTypeValue
);
1737 NS_ENSURE_SUCCESS(rv
, rv
);
1739 switch (simpleTypeValue
) {
1740 case nsISVSchemaSimpleType::SIMPLE_TYPE_RESTRICTION
: {
1741 // handle the facets
1743 nsCOMPtr
<nsISVSchemaRestrictionType
> restrictionType
=
1744 do_QueryInterface(simpleType
);
1746 nsCOMPtr
<nsISVSchemaFacet
> facet
;
1747 PRUint32 facetCounter
;
1750 // get the amount of restriction facet defined.
1751 rv
= restrictionType
->GetFacetCount(&facetCount
);
1752 NS_ENSURE_SUCCESS(rv
, rv
);
1753 LOG((" %d facet(s) defined.", facetCount
));
1755 // if we had enumerations, we may not add new ones, since we are
1756 // being restricted. So if x restricts y, x defines the possible
1757 // enumerations and any enumerations on y are skipped
1758 hasEnumerations
= (aDerived
->enumerationList
.Count() > 0);
1760 for (facetCounter
= 0; facetCounter
< facetCount
; ++facetCounter
) {
1761 rv
= restrictionType
->GetFacet(facetCounter
, getter_AddRefs(facet
));
1762 NS_ENSURE_SUCCESS(rv
, rv
);
1763 facet
->GetFacetType(&facetType
);
1765 switch (facetType
) {
1766 case nsISVSchemaFacet::FACET_TYPE_LENGTH
: {
1767 nsSchemaIntFacet
*length
= &aDerived
->length
;
1768 if (!length
->isDefined
) {
1769 length
->isDefined
= PR_TRUE
;
1770 facet
->GetLengthValue(&length
->value
);
1771 LOG((" - Length Facet found (value is %d)",
1777 case nsISVSchemaFacet::FACET_TYPE_MINLENGTH
: {
1778 nsSchemaIntFacet
*minLength
= &aDerived
->minLength
;
1779 if (!minLength
->isDefined
) {
1780 minLength
->isDefined
= PR_TRUE
;
1781 facet
->GetLengthValue(&minLength
->value
);
1782 LOG((" - Min Length Facet found (value is %d)",
1788 case nsISVSchemaFacet::FACET_TYPE_MAXLENGTH
: {
1789 nsSchemaIntFacet
*maxLength
= &aDerived
->maxLength
;
1790 if (!maxLength
->isDefined
) {
1791 maxLength
->isDefined
= PR_TRUE
;
1792 facet
->GetLengthValue(&maxLength
->value
);
1793 LOG((" - Max Length Facet found (value is %d)",
1799 case nsISVSchemaFacet::FACET_TYPE_PATTERN
: {
1800 nsSchemaStringFacet
*pattern
= &aDerived
->pattern
;
1801 if (!pattern
->isDefined
) {
1802 pattern
->isDefined
= PR_TRUE
;
1803 facet
->GetValue(pattern
->value
);
1804 LOG((" - Pattern Facet found (value is %s)",
1805 NS_ConvertUTF16toUTF8(pattern
->value
).get()));
1810 case nsISVSchemaFacet::FACET_TYPE_ENUMERATION
: {
1811 if (!hasEnumerations
) {
1812 facet
->GetValue(enumeration
);
1813 aDerived
->enumerationList
.AppendString(enumeration
);
1814 LOG((" - Enumeration found (%s)",
1815 NS_ConvertUTF16toUTF8(enumeration
).get()));
1820 case nsISVSchemaFacet::FACET_TYPE_WHITESPACE
: {
1821 if (!aDerived
->isWhitespaceDefined
)
1822 facet
->GetWhitespaceValue(&aDerived
->whitespace
);
1826 case nsISVSchemaFacet::FACET_TYPE_MAXINCLUSIVE
: {
1827 nsSchemaStringFacet
*maxInclusive
= &aDerived
->maxInclusive
;
1828 if (!maxInclusive
->isDefined
) {
1829 maxInclusive
->isDefined
= PR_TRUE
;
1830 facet
->GetValue(maxInclusive
->value
);
1831 LOG((" - Max Inclusive Facet found (value is %s)",
1832 NS_ConvertUTF16toUTF8(maxInclusive
->value
).get()));
1837 case nsISVSchemaFacet::FACET_TYPE_MININCLUSIVE
: {
1838 nsSchemaStringFacet
*minInclusive
= &aDerived
->minInclusive
;
1839 if (!minInclusive
->isDefined
) {
1840 minInclusive
->isDefined
= PR_TRUE
;
1841 facet
->GetValue(minInclusive
->value
);
1842 LOG((" - Min Inclusive Facet found (value is %s)",
1843 NS_ConvertUTF16toUTF8(minInclusive
->value
).get()));
1848 case nsISVSchemaFacet::FACET_TYPE_MAXEXCLUSIVE
: {
1849 nsSchemaStringFacet
*maxExclusive
= &aDerived
->maxExclusive
;
1850 if (!maxExclusive
->isDefined
) {
1851 maxExclusive
->isDefined
= PR_TRUE
;
1852 facet
->GetValue(aDerived
->maxExclusive
.value
);
1853 LOG((" - Max Exclusive Facet found (value is %s)",
1854 NS_ConvertUTF16toUTF8(maxExclusive
->value
).get()));
1859 case nsISVSchemaFacet::FACET_TYPE_MINEXCLUSIVE
: {
1860 nsSchemaStringFacet
*minExclusive
= &aDerived
->minExclusive
;
1861 if (!minExclusive
->isDefined
) {
1862 minExclusive
->isDefined
= PR_TRUE
;
1863 facet
->GetValue(minExclusive
->value
);
1864 LOG((" - Min Exclusive Facet found (value is %s)",
1865 NS_ConvertUTF16toUTF8(minExclusive
->value
).get()));
1870 case nsISVSchemaFacet::FACET_TYPE_TOTALDIGITS
: {
1871 nsSchemaIntFacet
*totalDigits
= &aDerived
->totalDigits
;
1872 if (!totalDigits
->isDefined
) {
1873 totalDigits
->isDefined
= PR_TRUE
;
1874 facet
->GetDigitsValue(&totalDigits
->value
);
1875 LOG((" - Totaldigits Facet found (value is %d)",
1876 totalDigits
->value
));
1881 case nsISVSchemaFacet::FACET_TYPE_FRACTIONDIGITS
: {
1882 nsSchemaIntFacet
*fractionDigits
= &aDerived
->fractionDigits
;
1883 if (!fractionDigits
->isDefined
) {
1884 fractionDigits
->isDefined
= PR_TRUE
;
1885 facet
->GetDigitsValue(&fractionDigits
->value
);
1886 LOG((" - FractionDigits Facet found (value is %d)",
1887 fractionDigits
->value
));
1895 nsresult rv
= restrictionType
->GetBaseType(getter_AddRefs(simpleType
));
1896 NS_ENSURE_SUCCESS(rv
, rv
);
1900 case nsISVSchemaSimpleType::SIMPLE_TYPE_BUILTIN
: {
1902 aDerived
->mBaseType
= simpleType
;
1907 case nsISVSchemaSimpleType::SIMPLE_TYPE_LIST
: {
1909 aDerived
->mBaseType
= simpleType
;
1914 case nsISVSchemaSimpleType::SIMPLE_TYPE_UNION
: {
1916 aDerived
->mBaseType
= simpleType
;
1926 // copies the data from aDerivedSrc to aDerivedDest
1928 nsSchemaValidatorUtils::CopyDerivedSimpleType(nsSchemaDerivedSimpleType
*aDerivedDest
,
1929 nsSchemaDerivedSimpleType
*aDerivedSrc
)
1931 aDerivedDest
->mBaseType
= aDerivedSrc
->mBaseType
;
1933 aDerivedDest
->length
.value
= aDerivedSrc
->length
.value
;
1934 aDerivedDest
->length
.isDefined
= aDerivedSrc
->length
.isDefined
;
1935 aDerivedDest
->minLength
.value
= aDerivedSrc
->minLength
.value
;
1936 aDerivedDest
->minLength
.isDefined
= aDerivedSrc
->minLength
.isDefined
;
1937 aDerivedDest
->maxLength
.value
= aDerivedSrc
->maxLength
.value
;
1938 aDerivedDest
->maxLength
.isDefined
= aDerivedSrc
->maxLength
.isDefined
;
1940 aDerivedDest
->pattern
.value
= aDerivedSrc
->pattern
.value
;
1941 aDerivedDest
->pattern
.isDefined
= aDerivedSrc
->pattern
.isDefined
;
1943 aDerivedDest
->isWhitespaceDefined
= aDerivedSrc
->isWhitespaceDefined
;
1944 aDerivedDest
->whitespace
= aDerivedSrc
->whitespace
;
1946 aDerivedDest
->maxInclusive
.value
= aDerivedSrc
->maxInclusive
.value
;
1947 aDerivedDest
->maxInclusive
.isDefined
= aDerivedSrc
->maxInclusive
.isDefined
;
1948 aDerivedDest
->minInclusive
.value
= aDerivedSrc
->minInclusive
.value
;
1949 aDerivedDest
->minInclusive
.isDefined
= aDerivedSrc
->minInclusive
.isDefined
;
1950 aDerivedDest
->maxExclusive
.value
= aDerivedSrc
->maxExclusive
.value
;
1951 aDerivedDest
->maxExclusive
.isDefined
= aDerivedSrc
->maxExclusive
.isDefined
;
1952 aDerivedDest
->minExclusive
.value
= aDerivedSrc
->minExclusive
.value
;
1953 aDerivedDest
->minExclusive
.isDefined
= aDerivedSrc
->minExclusive
.isDefined
;
1955 aDerivedDest
->totalDigits
.value
= aDerivedSrc
->totalDigits
.value
;
1956 aDerivedDest
->totalDigits
.isDefined
= aDerivedSrc
->totalDigits
.isDefined
;
1957 aDerivedDest
->fractionDigits
.value
= aDerivedSrc
->fractionDigits
.value
;
1958 aDerivedDest
->fractionDigits
.isDefined
= aDerivedSrc
->fractionDigits
.isDefined
;
1960 aDerivedDest
->enumerationList
= aDerivedSrc
->enumerationList
;
1963 // sets aResultNode to aNode, making sure it points to null or a dom element
1965 nsSchemaValidatorUtils::SetToNullOrElement(nsIDOMNode
*aNode
,
1966 nsIDOMNode
**aResultNode
)
1968 nsCOMPtr
<nsIDOMNode
> currentNode(aNode
), tmpNode
;
1972 currentNode
->GetNodeType(&nodeType
);
1974 // if not an element node, skip
1975 while (currentNode
&& nodeType
!= nsIDOMNode::ELEMENT_NODE
) {
1976 currentNode
->GetNextSibling(getter_AddRefs(tmpNode
));
1977 currentNode
= tmpNode
;
1979 currentNode
->GetNodeType(&nodeType
);
1982 currentNode
.swap(*aResultNode
);
1988 nsSchemaValidatorUtils::FindCharInSet(const nsAString
& aString
,
1989 const char *aSet
, PRInt32 aOffset
)
1991 if (aString
.IsEmpty()) {
1997 } else if (aOffset
> (PRInt32
)aString
.Length()) {
2001 const PRUnichar
*start
, *end
;
2002 aString
.BeginReading(&start
, &end
);
2004 for (; start
!= end
; ++start
) {
2005 for (const char *temp
= aSet
; *temp
; ++temp
) {
2006 if (*start
== PRUnichar(*temp
)) {
2007 return (temp
- aSet
+ aOffset
) ;