00001
00002
00003 namespace HTML
00004 {
00026 struct AttributeValues
00027 {
00031 struct AttributeValue
00032 {
00034 bool valid;
00035 AttributeValue(bool val = false) : valid(val) {}
00036 virtual ~AttributeValue() {}
00037 };
00038
00040 struct Direction : public AttributeValue
00041 {
00043 bool leftToRight;
00044 Direction(bool _leftToRight) : AttributeValue(true), leftToRight(_leftToRight) {}
00045 };
00046
00048 struct Align : public AttributeValue
00049 {
00051 enum AllowedAlign { Left = 0, Right = 1, Center = 2, Justify = 3, Char = 4, Top = 5, Bottom = 6, Middle = 7, BaseLine = 8 } align;
00052 Align(const AllowedAlign & val = Left) : AttributeValue(true), align(val) {}
00053 };
00054
00056 struct TextFlow : public AttributeValue
00057 {
00059 enum AllowedFlow { Left = 0, Right = 1, All = 2, None = 3 } flow;
00060 TextFlow(const AllowedFlow & val = Left) : AttributeValue(true), flow(val) {}
00061 };
00062
00066 template <class T>
00067 struct Array : public AttributeValue
00068 {
00069 T * array;
00070 const int length;
00071
00072 Array(T * _array, const int _length) : AttributeValue(true), array(_array), length(_length) {}
00073 virtual ~ContentTypes() { delete[] array; array = 0; length = 0; }
00074 };
00075
00077 struct Text : public AttributeValue
00078 {
00080 String value;
00081 TextFlow(const tchar * const input, const int length) : AttributeValue(true), value(input, length) { value.CleanHTMLEntities(); }
00082 };
00083 typedef Array<Text> IDRefs;
00084
00085
00090 struct Charset : public AttributeValue
00091 {
00092 enum AllowedMIB
00093 {
00094 ASCII = 3,
00095 Latin1 = 4,
00096 } mib;
00097 Charset(const AllowedMIB & _mib = ASCII) : AttributeValue(true), mib(_mib) {}
00098 };
00099 typedef Array<Charset> Charsets;
00100
00102 struct ContentType : public AttributeValue
00103 {
00104 String value;
00105 ContentType(const tchar * const input, const int length) : AttributeValue(true), value(input, length) {}
00106 };
00107 typedef Array<ContentType> ContentTypes;
00108
00110 struct Character : public AttributeValue
00111 {
00112 tchar character;
00113 Character(const tchar inp = 0) : AttributeValue(true), character(inp) {}
00114 };
00115
00117 struct URI : public AttributeValue
00118 {
00119 const String scheme;
00120 const String authority;
00121 const String path;
00122 const String query;
00123 const String fragment;
00124 URI(const String & _scheme, const String & _authority, const String & _path, const String & _query, const String & _fragment) : AttributeValue(true),
00125 scheme(_scheme), authority(_authority), path(_path), query(_query), fragment(_fragment) {}
00126
00128 inline String buildURI() const
00129 {
00130 String uri;
00131 if (!scheme.isEmpty()) uri += scheme + ':';
00132 if (!authority.isEmpty()) uri += "//" + authority;
00133 uri += path;
00134 if (!query.isEmpty()) uri += '?' + query;
00135 if (!fragment.isEmpty()) uri += '#' + fragment;
00136 return uri;
00137 }
00138
00140 inline void buildURI(String & uri) const
00141 {
00142 uri = String::Empty;
00143 if (!scheme.isEmpty()) uri += scheme + ':';
00144 if (!authority.isEmpty()) uri += "//" + authority;
00145 uri += path;
00146 if (!query.isEmpty()) uri += '?' + query;
00147 if (!fragment.isEmpty()) uri += '#' + fragment;
00148 }
00149 };
00150
00154 struct Color : public AttributeValue
00155 {
00156 uint8 R, G, B;
00157 Color(const uint8 _R, const uint8 _G, const uint8 _B) : AttributeValue(true), R(_R), G(_G), B(_B) {}
00158 Color(const tchar * const input, const int length) : AttributeValue(true)
00159 {
00160 if (length == 6 && areHex(input, 6))
00161 {
00162 R = fromHex(input[0], input[1]);
00163 G = fromHex(input[2], input[3]);
00164 B = fromHex(input[4], input[5]);
00165 } else if (length = 3 && areHex(input, 3))
00166 {
00167 R = fromHex(input[0], input[0]);
00168 G = fromHex(input[1], input[1]);
00169 B = fromHex(input[2], input[2]);
00170 } else if (length > 6 && input[0] == 'r' && input[1] == 'g' && input[2] == 'b')
00171 {
00172
00173
00174 } else valid = false;
00175 }
00176
00177 bool areHex(const tchar * input, const int length)
00178 {
00179 const tchar * const ptr = input + length;
00180 while (input < ptr) if (!isHex(*input)) return false; else input++;
00181 return true;
00182 }
00183
00184 uint8 fromHex(const tchar high, const tchar low) { uint8 val = ((high > '9' ? (high - 'a' + 10) : high - '0') << 4) | (low > '9' ? (low - 'a' + 10) : low - '0'); }
00185 };
00186
00190 struct Length : public AttributeValue
00191 {
00193 float value;
00194 enum AllowedUnit { Pixels, Element, Percent, XHeight, Inches, Centimeters, Millimeters, Points, Picas, Relative } unit;
00195 Length(const float & val = 0, const AllowedUnit & _unit) : AttributeValue(true), value(val), unit(_unit) {}
00196 };
00197 typedef Array<Length> Coords;
00198
00200 struct Boolean : public AttributeValue
00201 {
00202 bool value;
00203 Boolean(const bool & val = true) : AttributeValue(true), value(val) {}
00204 };
00205
00209 struct DateTime : public AttributeValue
00210 {
00211 unsigned int year;
00212 unsigned int month;
00213 unsigned int day;
00214 unsigned int hour;
00215 unsigned int min;
00216 unsigned int sec;
00217 DateTime(const unsigned int & _year, const unsigned int & _month, const unsigned int & _day, const unsigned int & _hour = 0, const unsigned int & _min = 0, const unsigned int & _sec = 0)
00218 : AttributeValue(true), year(_year), month(_month), day(_day), hour(_hour), min(_min), sec(_sec) { }
00219 };
00220
00222 struct TFrame : public AttributeValue
00223 {
00224 enum AllowedFrame { Void = 0, Above = 1, Below = 2, HSides = 3, LHS = 4, RHS = 5, VSides = 6, Box = 7, Border = 8} frame;
00225 TFrame(const AllowedFrame & val) : AttributeValue(true), frame(val) {}
00226 };
00227
00229 struct LanguageCode : public AttributeValue
00230 {
00231 String primary;
00232 String sub;
00233 LanguageCode(const String & prim, const String & _sub = "") : AttributeValue(true), primary(prim), sub(_sub) {}
00234 };
00235
00237 struct MediaDesc : public AttributeValue
00238 {
00239 enum AllowedMedia { Screen = 1, TTY = 2, TV = 3, Projection = 4, Handheld = 5, Print = 6, Braille = 7, Aural = 8, All = 9 } media;
00240 MediaDesc(const AllowedMedia & val) : AttributeValue(true), media(val) {}
00241 };
00242
00243 typedef Array<MediaDesc> MediaDescs;
00244
00246 struct FormMethod : public AttributeValue
00247 {
00248 enum AllowedMethod { Get = 0, Post = 1 } method;
00249 FormMethod(const AllowedMethod & val) : AttributeValue(true), method(val) {}
00250 };
00251
00253 struct Script : public AttributeValue
00254 {
00255 String script;
00256 Script(const tchar * const input, const int length) : AttributeValue(true), script(input, length) {}
00257 };
00258
00260 struct LinkType : public AttributeValue
00261 {
00262 String name;
00263 enum DefinedType { Other = 0, Alternate = 1, StyleSheet = 2, Start = 3, Next = 4, Prev = 5, Contents = 6, Index = 7, Glossary = 8, Copyright = 9, Chapter = 10, Section = 11, Subsection = 12, Appendix = 13, Help = 14, Bookmark = 15 } type;
00264 LinkType(const tchar * const input, const int length, const DefinedType & val = Other) : AttributeValue(true), name(input, length), type(val) {}
00265 };
00266 typedef Array<LinkType> LinkTypes;
00267
00269 struct TRules : public AttributeValue
00270 {
00271 enum AllowedRules { None = 0, Groups = 1, Rows = 2, Cols = 3, All = 4} rule;
00272 TRules(const AllowedRules & val) : AttributeValue(true), rule(val) {}
00273 };
00274
00276 struct Scope : public AttributeValue
00277 {
00278 enum AllowedScope { Row = 0, Col = 1, RowGroup = 2, ColGroup = 3} scope;
00279 Scope(const AllowedScope & val) : AttributeValue(true), scope(val) {}
00280 };
00281
00283 struct Scrolling : public AttributeValue
00284 {
00285 enum AllowedValue { No = 0, Yes = 1, Auto = 2 } value;
00286 Scrolling(const AllowedValue & val) : AttributeValue(true), value(val) {}
00287 };
00288
00290 struct Shape : public AttributeValue
00291 {
00292 enum AllowedShape { Rect = 0, Circle = 1, Polygon = 2, Default = 3} shape;
00293 Shape(const AllowedShape & val) : AttributeValue(true), shape(val) {}
00294 };
00295
00296
00297
00298 typedef Text Style;
00299
00301 struct FrameTarget : public AttributeValue
00302 {
00303 enum SpecialTargets { Other = 0, Blank = 1, Self = 1, Parent = 2, Top = 3} target;
00304 String name;
00305 FrameTarget(const tchar * const input, const int length, const SpecialTargets & val = Other) : AttributeValue(true), name(input, length), target(val) {}
00306 }
00307
00309 struct InputType : public AttributeValue
00310 {
00311 enum AllowedInputs { Text = 0, Password = 1, Checkbox = 2, Radio = 3, Submit = 4, Reset = 5, File = 6, Hidden = 7, Image = 8, Button = 9} type;
00312 InputType(const AllowedInputs & val) : AttributeValue(true), type(val) {}
00313 };
00314
00316 struct ListStyle : public AttributeValue
00317 {
00318 enum AllowedStyle { Disc = 0, Square = 1, Circle = 2, One = 3, UpperAlpha, LowerAlpha, UpperRoman, LowerRoman} style;
00319 ListStyle(const AllowedStyle & val) : AttributeStyle(true), style(val) {}
00320 };
00321
00323 struct ButtonType : public AttributeValue
00324 {
00325 enum AllowedTypes { Button = 0, Submit = 1, Reset = 2} type;
00326 ButtonType(const AllowedTypes & val) : AttributeStyle(true), type(val) {}
00327 };
00328
00330 struct ValueType : public AttributeValue
00331 {
00332 enum AllowedTypes { Data = 0, Ref = 1, Object = 2} type;
00333 ValueType(const AllowedTypes & val) : AttributeStyle(true), type(val) {}
00334 };
00335 };
00336
00337
00338 AttributeValue InvalidValue = { false };
00340 typedef AttributeValue & (*AttributeValidationFunctionsPointer)(const AttributeValueAllocator & alloc, const tchar * const input, const int length);
00341 AttributeValue (*AttributeValidationFunctionsPointer)(const tchar * const input, const int length);
00342
00343 #define CheckMaxLength(X) if (length > X) return InvalidValue
00344 #define CheckMinLength(X) if (length < X) return InvalidValue
00345 #define CheckMinMaxLength(X, Y) if (length < X || length > Y ) return InvalidValue
00346 #define MakeMagic(W,X,Y,Z) ((Z << 24) | (Y << 16) | (X << 8) | W)
00347 #define QCheck_32(X,Y) ((X) ^ Y == 0)
00348 #define QCheck_24(X,Y) ((X & 0xffffff) ^ Y == 0)
00349 #define QCheck_16(X,Y) ((X & 0xffffff) ^ Y == 0)
00350 #define QCheck_8(X,Y) ((X & 0xffff) ^ Y == 0)
00351 #define QCheck(X,Y,M) QCheck_##M
00352 inline AttributeValue & Validate_Direction (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00353 { CheckMinMaxLength(3, 3);
00354 unsigned int value = *reinterpret_cast<const unsigned int* const>(input);
00355 static const unsigned int ltr = MakeMagic(0, 'l', 't', 'r');
00356 static const unsigned int rtl = MakeMagic(0, 'r', 't', 'l');
00357 if (QCheck(value, ltr, 24)) return alloc.getNew((AttributeValues::Direction *)0, true);
00358 if (QCheck(value, rtl, 24)) return alloc.getNew((AttributeValues::Direction *)0, false);
00359 return InvalidValue;
00360 }
00361
00362 inline AttributeValue & Validate_LeftCenterRight (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00363 { CheckMinMaxLength(4, 6);
00364 unsigned int value = *reinterpret_cast<const unsigned int* const>(input);
00365 static const unsigned int left = MakeMagic('l', 'e', 'f', 't');
00366 static const unsigned int right = MakeMagic('r', 'i', 'g', 'h');
00367 static const unsigned int center = MakeMagic('c', 'e', 'n', 't');
00368 if (length == 4 && QCheck(value, left, 32)) return alloc.getNew((AttributeValues::Align *)0, AttributeValues::Align::Left);
00369 if (length == 5 && QCheck(value, right, 32) && input[4] == 't') return alloc.getNew((AttributeValues::Align *)0, AttributeValues::Align::Right);
00370 if (length == 6 && QCheck(value, center, 32) && input[4] == 'e' && input[5] == 'r') return alloc.getNew((AttributeValues::Align *)0, AttributeValues::Align::Center);
00371 return InvalidValue;
00372 }
00373
00374 inline AttributeValue & Validate_LeftCenterRightJustify (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00375 { AttributeValue ret = Validate_LeftCenterRight(input, length);
00376 if (ret.valid) return ret;
00377 unsigned int value = *reinterpret_cast<const unsigned int* const>(input);
00378 static const unsigned int justify = MakeMagic('j', 'u', 's', 't');
00379 if (length == 7 && QCheck(value, justify, 32) && input[4] == 'i' && input[5] == 'f' && input[6] == 'y') return alloc.getNew((AttributeValues::Align *)0, AttributeValues::Align::Justify);
00380 return InvalidValue;
00381 }
00382
00383 AttributeValue Validate_LeftCenterRightJustifyChar(const tchar * const input, const int length)
00384 { AttributeValue ret = Validate_LeftCenterRightJustify(input, length);
00385 if (ret.valid) return ret;
00386 unsigned int value = *reinterpret_cast<const unsigned int* const>(input);
00387 static const unsigned int _char = MakeMagic('c', 'h', 'a', 'r');
00388 if (length == 4 && QCheck(value, _char, 32)) return alloc.getNew((AttributeValues::Align *)0, AttributeValues::Align::Char);
00389 return InvalidValue;
00390 }
00391
00392 AttributeValue & Validate_LeftAllRightNone (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00393 { CheckMinMaxLength(4, 6);
00394 unsigned int value = *reinterpret_cast<const unsigned int* const>(input);
00395 static const unsigned int left = MakeMagic('l', 'e', 'f', 't');
00396 static const unsigned int right = MakeMagic('r', 'i', 'g', 'h');
00397 static const unsigned int all = MakeMagic(0, 'a', 'l', 'l');
00398 static const unsigned int none = MakeMagic('n', 'o', 'n', 'e');
00399 if (length == 4)
00400 {
00401 if (QCheck(value, left, 32)) return alloc.getNew((AttributeValues::TextFlow *)0, AttributeValues::TextFlow::Left);
00402 if (QCheck(value, none, 32)) return alloc.getNew((AttributeValues::TextFlow *)0, AttributeValues::TextFlow::None);
00403 }
00404 if (length == 5 && QCheck(value, right, 32) && input[4] == 't') return alloc.getNew((AttributeValues::TextFlow *)0, AttributeValues::TextFlow::Right);
00405 if (length == 3 && QCheck(value, all, 24)) return alloc.getNew((AttributeValues::TextFlow *)0, AttributeValues::TextFlow::All);
00406 return InvalidValue;
00407 }
00408
00409 AttributeValue & Validate_Text (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00410 { return alloc.getNew((AttributeValues::Text *)0, input, length); }
00411
00412 inline template <class T, class U>
00413 AttributeValue SplitBasedOn( const tchar * const input, const int length, T * , U *, const tchar ch, AttributeValidationFunctionsPointer func_ptr)
00414 {
00415 int len = length;
00416
00417 while (input[len - 1] == ch) len--;
00418 int count = countChar(input, len, ch) + 1, i = 0;
00419 if (count)
00420 {
00421 U * array = new U[charsetCount];
00422 if (!array) return InvalidValue;
00423
00424 const tchar * ptr = input;
00425 int len = length;
00426 while (i < count - 1)
00427 {
00428 int pos = findChar(ptr, len, ch);
00429 array[i] = func_ptr(ptr, pos ? pos : len);
00430 len -= pos;
00431 ptr = &input[length - len - 1];
00432 ++i;
00433 }
00434 array[i] = func_ptr(ptr, len);
00435 return T(array, count);
00436 }
00437 return InvalidValue;
00438 }
00439
00440
00441 AttributeValue & Validate_Charsets (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00442 { return SplitBasedOn(input, length, (AttributeValues::Charsets*)0, (AttributeValues::Charset*)0, ' ', Validate_Charset); }
00443
00444 AttributeValue & Validate_ContentTypes (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00445 { return SplitBasedOn(input, length, (AttributeValues::ContentTypes*)0, (AttributeValues::ContentType*)0, ',', Validate_ContentType); }
00446
00447 AttributeValue & Validate_Character (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00448 { CheckMaxLength(1)
00449 return alloc.getNew((AttributeValues::Character *)0, input[0]);
00450 }
00451
00452 #define isIn(X, Y) _isIn(X, sizeof(X) / sizeof(X[0]), Y)
00453 inline bool _isIn(const tchar * array, const unsigned int len, tchar ch)
00454 {
00455 for (unsigned int i = 0; i < len; ++i)
00456 if (array[i] == ch) return true;
00457 return false;
00458 }
00459 inline bool isHex(const tchar a) { return (a >= '0' && a <= '9') || (a >= 'a' && a <= 'f') || (a >= 'A' && a <= 'F'); }
00460
00461
00462 AttributeValue & Validate_URI (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00463 {
00464 static const tchar reserved[] = { ';', '/', '?', ':', '@', '&', '=', '+', '$', ',' };
00465 static const tchar less_reserved[] = { ';', ':', '@', '&', '=', '+', '$', ',' };
00466 static const tchar unreserved[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
00467 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
00468 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
00469 '-', '_', '.', '!', '~', '*', '\'', '(', ')' };
00470 static const tchar escaped[] = { '%', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'a', 'b', 'c', 'd', 'e', 'f' };
00471 static const tchar excluded[] = { '{', '}', '|', '\\', '^', '[', ']', '`' };
00472 static const tchar breakScheme[] = { ':', '/', '?', '#' };
00473
00474 int i = 0;
00475 int scheme_e = 0, auth_s = 0, auth_e = 0, path_s = 0, path_e = 0, query_s = 0, query_e = 0, frag_s = 0, frag_e = 0;
00476 int absoluteURI = 0, hier_part = 0, opaque_part = 0, net_path = 0, relativeURI = 0;
00477
00478 while (i < length)
00479 {
00480 if (input[i] < 0x21 || (unsigned char)input[i] > 0x7F) return InvalidValue;
00481 if (input[i] == '<' || input[i] == '>' || input[i] == '"') return InvalidValue;
00482
00483 if (input[i] == '%')
00484 {
00485 if ((i + 2 > length || !isHex(input[i+1]) || !isHex(input[i+2]))) return InvalidValue;
00486 i+= 2; continue;
00487 }
00488 if (isIn(excluded, input[i])) return InvalidValue;
00489
00490 if (!absoluteURI && isIn(breakScheme, input[i]))
00491 {
00492 if (input[i] == ':')
00493 {
00494 scheme_e = i; absoluteURI = 1;
00495 if (i + 1 < length && input[i+1] == '/') { hier_part = 1; ++i; }
00496 else if (i + 1 < length && input[i+1] != '/') { opaque_part = 1; ++i; }
00497 }
00498 else { absoluteURI = 0; relativeURI = 1; }
00499 ++i; continue;
00500 }
00501 ++i;
00502 }
00503
00504 i = 0;
00505 if (absoluteURI)
00506 {
00507 if (scheme_e) i = scheme_e + 1;
00508 if (i+1 < length)
00509 {
00510 if (hier_part)
00511 {
00512 if (input[i+1] == '/')
00513 {
00514 net_path = 1;
00515 i += 2;
00516 auth_s = i;
00517
00518 while (i < length && (isIn(unreserved, input[i]) || input[i] == '%' || isIn(less_reserved, input[i]))) ++i;
00519 auth_e = i;
00520 }
00521
00522
00523 if (i < length && input[i] == '/')
00524 {
00525
00526 path_s = i;
00527 while (i < length && input[i] != '?' && input[i] != '#') ++i;
00528 path_e = i;
00529
00530
00531 if (input[i] == '?')
00532 { query_s = i+1;
00533 ++i;
00534 while (i < length && input[i] != '#') ++i;
00535 query_e = i;
00536 }
00537 }
00538 } else if (opaque_part)
00539 {
00540
00541 path_s = i;
00542 while (i < length && (isIn(unreserved, input[i]) || input[i] == '%' || isIn(reserved, input[i]))) ++i;
00543 path_e = i;
00544
00545
00546 }
00547
00548 }
00549 } else if (relativeURI)
00550 {
00551 if (i+1 < length && input[i] == '/' && input[i+1] == '/')
00552 {
00553 net_path = 1; ++i;
00554 auth_s = i;
00555
00556 while (i < length && (isIn(unreserved, input[i]) || input[i] == '%' || isIn(less_reserved, input[i]))) ++i;
00557 auth_e = i;
00558
00559
00560 if (i < length && input[i] == '/')
00561 {
00562
00563 path_s = i;
00564 while (i < length && input[i] != '?' && input[i] != '#') ++i;
00565 path_e = i;
00566
00567
00568 if (i < length && input[i] == '?')
00569 { query_s = i+1;
00570 ++i;
00571 while (i < length && input[i] != '#') ++i;
00572 query_e = i;
00573 }
00574 }
00575 } else if (i < length)
00576 {
00577
00578 path_s = i;
00579 while (i < length && (isIn(unreserved, input[i]) || input[i] == '%' || isIn(reserved, input[i])) && input[i] != '?') ++i;
00580 path_e = i;
00581
00582 if (i < length && input[i] == '?')
00583 { query_s = i+1;
00584 ++i;
00585 while (i < length && input[i] != '#') ++i;
00586 query_e = i;
00587 }
00588
00589 }
00590 }
00591
00592
00593 if (i < length && input[i] == '#')
00594 {
00595 frag_s = i+1;
00596 frag_e = length;
00597 }
00598
00599 return alloc.getNew((AttributeValues::URI *)0, scheme_e ? String(input, scheme_e) : String(""), auth_e ? String(&input[auth_s], auth_e - auth_s) : String(""), path_e ? String(&input[path_s], path_e - path_s) : String(""), query_e ? String(&input[query_s], query_e - query_s) : String(""), frag_e ? String(&input[frag_e], frag_e - frag_s) : String(""));
00600 }
00601
00603 int AllowedStringInNameOrID(const tchar * const input, const int length)
00604 {
00605 static tchar allowed[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
00606 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
00607 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
00608 '-', '_', '.', ':' };
00609 bool ok = true; int i = 0;
00610 while (i < length) if (!isIn(allowed, input[i])) return i; else ++i;
00611 return i;
00612 }
00613
00614 AttributeValue & Validate_CAlign (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00615 { CheckMinMaxLength(3, 6);
00616 unsigned int value = *reinterpret_cast<const unsigned int* const>(input);
00617 static const unsigned int left = MakeMagic('l', 'e', 'f', 't');
00618 static const unsigned int right = MakeMagic('r', 'i', 'g', 'h');
00619 static const unsigned int top = MakeMagic(0, 't', 'o', 'p');
00620 static const unsigned int bottom = MakeMagic('b', 'o', 't', 't');
00621 if (length == 3 && QCheck(value, top, 24)) return alloc.getNew((AttributeValues::Align *)0, AttributeValues::Align::Top);
00622 if (length == 4 && QCheck(value, left, 32)) return alloc.getNew((AttributeValues::Align *)0, AttributeValues::Align::Left);
00623 if (length == 5 && QCheck(value, right, 32) && input[4] == 't') return alloc.getNew((AttributeValues::Align *)0, AttributeValues::Align::Right);
00624 if (length == 6 && QCheck(value, bottom, 32) && input[4] == 'o' && input[5] == 'm') return alloc.getNew((AttributeValues::Align *)0, AttributeValues::Align::Bottom);
00625 return InvalidValue;
00626 }
00627
00628 AttributeValue & Validate_IAlign (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00629 { AttributeValue ret = Validate_CAlign(input, length);
00630 if (ret.valid) return ret;
00631 unsigned int value = *reinterpret_cast<const unsigned int* const>(input);
00632 static const unsigned int _char = MakeMagic('m', 'i', 'd', 'd');
00633 if (length == 6 && QCheck(value, _char, 32) && input[4] == 'l' && input[5] == 'e') return alloc.getNew((AttributeValues::Align *)0, AttributeValues::Align::Middle);
00634 return InvalidValue;
00635 }
00636
00637 AttributeValue & Validate_LAlign (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00638 { return Validate_CAlign(input, length); }
00639
00640 AttributeValue & Validate_TAlign (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00641 { return Validate_LeftCenterRight(input, length); }
00642
00643 AttributeValue & Validate_Color (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00644 { CheckMinLength(1);
00645
00646 if (input[0] == '#')
00647 return AttributeValue::Color(&input[1], length);
00648
00649
00650 static const tchar * webColors[] = { "black:#000000", "green:#008000", "silver:#c0c0c0",
00651 "lime:#00ff00", "gray:#808080", "olive:#808000",
00652 "white:#ffffff", "yellow:#ffff00", "maroon:#800000",
00653 "navy:#000080", "red:#ff0000", "blue:#0000ff",
00654 "purple:#800080", "teal:#008080", "fuschia:#ff00ff",
00655 "aqua:#00ffff", NULL
00656 };
00657 const tchar ** ptr = webColors[0];
00658 while (*ptr)
00659 {
00660 unsigned int len = findLength(*ptr);
00661 if (findInString(*ptr, len, input, length)) return AttributeValue::Color(&(*ptr)[len - 6], 6);
00662 }
00663 return InvalidValue;
00664 }
00665
00666 AttributeValue & Validate_CDATA (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00667 { return alloc.getNew((AttributeValues::Text *)0, input, length); }
00668
00669 AttributeValue & Validate_Pixels (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00670 { int value = fromStringToInteger(input, length);
00671 return alloc.getNew((AttributeValues::Length *)0, (float)value, AttributeValues::Length::Pixels);
00672 }
00673
00674 AttributeValue & Validate_Length (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00675 { if (input[length - 1] == '%') return alloc.getNew((AttributeValues::Length *)0, fromStringToFloat(input, length), AttributeValues::Length::Percent);
00676 int value = fromStringToInteger(input, length);
00677 return alloc.getNew((AttributeValues::Length *)0, (float)value, AttributeValues::Length::Pixels);
00678 }
00679
00680 AttributeValue & Validate_Charset (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00681 {
00682
00683 static const char * allowedCharsets[] = { "iso_8859-1", "iso-8859-1", "latin1", "l1", "ibm819", "cp819", "csisolatin1", "iso-ir-100",
00684 "iso-ir-6", "ansi_x3.4-1986", "iso_646.irv:1991", "ascii", "iso646-us", "us-ascii", "us", "ibm367", "cp367", "csASCII",
00685 NULL };
00686 const char ** ptr = allowedCharsets[0];
00687 for (; ptr != allowedCharsets[9]; ptr++)
00688 {
00689 int len = strlen(*ptr);
00690 if (findInString(input, length, ptr, len))
00691 return alloc.getNew((AttributeValues::Charset *)0, AttributeValues::Charset::Latin1);
00692 }
00693 for (; *ptr; ptr++)
00694 {
00695 int len = strlen(*ptr);
00696 if (findInString(input, length, ptr, len))
00697 return alloc.getNew((AttributeValues::Charset *)0, AttributeValues::Charset::ASCII);
00698 }
00699 return InvalidValue;
00700 }
00701
00702 AttributeValue ValidateBooleans(const tchar * const input, const int length, const tchar * const booleanName)
00703 { if (!length) return alloc.getNew((AttributeValues::Boolean *)0, true);
00704 if (length == findLength(booleanName) && findInString(input, length, booleanName, length)) return alloc.getNew((AttributeValues::Boolean *)0, true);
00705 return InvalidValue;
00706 }
00707
00708 AttributeValue & Validate_Checked (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00709 { static const tchar * checked = "checked"; return ValidateBooleans(input, length, checked); }
00710
00711 AttributeValue & Validate_ContentType (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00712 { return alloc.getNew((AttributeValues::ContentType *)0, input, length); }
00713
00714 AttributeValue & Validate_MultiLengths (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00715 { return SplitBasedOn(input, length, (AttributeValues::MultiLengths*)0, (AttributeValues::MultiLength*)0, ',', Validate_MultiLength); }
00716
00717 AttributeValue & Validate_Number (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00718 { return alloc.getNew((AttributeValues::Length *)0, fromStringToInteger(input, length), AttributeValues::Length::Pixels); }
00719
00720 AttributeValue & Validate_Compact (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00721 { static const tchar * compact = "compact"; return ValidateBooleans(input, length, compact); }
00722
00723 AttributeValue & Validate_Coords (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00724 { return SplitBasedOn(input, length, (AttributeValues::Coords*)0, (AttributeValues::Length*)0, ',', Validate_Length); }
00725
00726
00727 AttributeValue & Validate_Datetime (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00728 { CheckMinMaxLength(8, 11);
00729 int year = fromStringToInteger(input, 4), int pos = 4;
00730 if (input[pos] == '-') pos++;
00731 int month = fromStringToInteger(&input[pos], 2);
00732 pos += 2 + (input[pos] == '-');
00733 if (pos + 2 > length) return InvalidValue;
00734 int day = fromStringToInteger(&input[pos], 2);
00735 if (pos + 3 > length) return alloc.getNew((AttributeValues::DateTime *)0, year, month, day);
00736 pos += 2 + (input[pos] == ' ' || input[pos] == 'T');
00737 int hour = fromStringToInteger(&input[pos], 2);
00738 if (pos + 3 > length) return alloc.getNew((AttributeValues::DateTime *)0, year, month, day);
00739 pos += 2 + (input[pos] == ':');
00740 int min = fromStringToInteger(&input[pos], 2);
00741 if (pos + 3 > length) return alloc.getNew((AttributeValues::DateTime *)0, year, month, day, hour, min);
00742 pos += 2 + (input[pos] == ':');
00743 int sec = fromStringToInteger(&input[pos], 2);
00744 return alloc.getNew((AttributeValues::DateTime *)0, year, month, day, hour, min, sec);
00745 }
00746
00747 AttributeValue & Validate_Declare (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00748 { static const tchar * declare = "declare"; return ValidateBooleans(input, length, declare); }
00749 AttributeValue & Validate_Defer (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00750 { static const tchar * defer = "defer"; return ValidateBooleans(input, length, defer); }
00751 AttributeValue & Validate_Disabled (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00752 { static const tchar * disabled = "disabled"; return ValidateBooleans(input, length, disabled); }
00753
00754 AttributeValue & Validate_IDRef (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00755 { if (AllowedStringInNameOrID(input, length) != length) return InvalidValue;
00756 return Validate_Text(input, length); }
00757
00758 AttributeValue & Validate_TFrame (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00759 { CheckMinMaxLength(3, 6);
00760 unsigned int value = *reinterpret_cast<const unsigned int* const>(input);
00761 static const unsigned int border = MakeMagic('b', 'o', 'r', 'd');
00762 static const unsigned int hsides = MakeMagic('h', 's', 'i', 'd');
00763 static const unsigned int vsides = MakeMagic('v', 's', 'i', 'd');
00764 static const unsigned int box = MakeMagic(0, 'b', 'o', 'x');
00765 static const unsigned int lhs = MakeMagic(0, 'l', 'h', 's');
00766 static const unsigned int rhs = MakeMagic(0, 'r', 'h', 's');
00767 static const unsigned int _void = MakeMagic('v', 'o', 'i', 'd');
00768 static const unsigned int above = MakeMagic('a', 'b', 'o', 'v');
00769 static const unsigned int below = MakeMagic('b', 'e', 'l', 'o');
00770 if (length == 6)
00771 {
00772 if (QCheck(value, border, 32) && input[4] == 'e' && input[5] == 'r') return alloc.getNew((AttributeValues::TFrame *)0, AttributeValues::TFrame::Border);
00773 if (QCheck(value, hsides, 32) && input[4] == 'e' && input[5] == 's') return alloc.getNew((AttributeValues::TFrame *)0, AttributeValues::TFrame::HSides);
00774 if (QCheck(value, vsides, 32) && input[4] == 'e' && input[5] == 's') return alloc.getNew((AttributeValues::TFrame *)0, AttributeValues::TFrame::VSides);
00775 }
00776 if (length == 5)
00777 {
00778 if (QCheck(value, above, 32) && input[4] == 'e') return alloc.getNew((AttributeValues::TFrame *)0, AttributeValues::TFrame::Above);
00779 if (QCheck(value, below, 32) && input[4] == 'w') return alloc.getNew((AttributeValues::TFrame *)0, AttributeValues::TFrame::Below);
00780 }
00781 if (length == 4)
00782 if (QCheck(value, _void, 32)) return alloc.getNew((AttributeValues::TFrame *)0, AttributeValues::TFrame::Void);
00783 if (length == 3)
00784 {
00785 if (QCheck(value, box, 24)) return alloc.getNew((AttributeValues::TFrame *)0, AttributeValues::TFrame::Box);
00786 if (QCheck(value, lhs, 24)) return alloc.getNew((AttributeValues::TFrame *)0, AttributeValues::TFrame::LHS);
00787 if (QCheck(value, rhs, 24)) return alloc.getNew((AttributeValues::TFrame *)0, AttributeValues::TFrame::RHS);
00788 }
00789 return InvalidValue;
00790 }
00791
00792 AttributeValue & Validate_NumericBoolean (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00793 { CheckMinMaxLength(1, 1);
00794 if (input[0] == '1') return alloc.getNew((AttributeValues::Boolean *)0, true);
00795 if (input[0] == '0') return alloc.getNew((AttributeValues::Boolean *)0, false);
00796 return InvalidValue;
00797 }
00798
00799 AttributeValue & Validate_IDRefs (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00800 { return SplitBasedOn(input, length, (AttributeValues::IDRefs*)0, (AttributeValues::Text*)0, ' ', Validate_IDRef); }
00801
00802 AttributeValue & Validate_LanguageCode (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00803 {
00804 CheckMinMaxLength(2, 17);
00805 int pos = findChar(input, length, '-');
00806 if (pos == -1) return alloc.getNew((AttributeValues::LanguageCode *)0, String(input, length));
00807 else return alloc.getNew((AttributeValues::LanguageCode *)0, String(input, pos), String(&input[pos+1], length - pos - 1));
00808 }
00809
00810 AttributeValue & Validate_Name (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00811 { if (AllowedStringInNameOrID(input, length) != length) return InvalidValue;
00812 return Validate_Text(input, length); }
00813
00814 AttributeValue & Validate_ID (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00815 { return Validate_Name(input, length); }
00816
00817 AttributeValue & Validate_IsMap (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00818 { static const tchar * ismap = "ismap"; return ValidateBooleans(input, length, ismap); }
00819
00820
00821 AttributeValue Val_MediaDesc (const tchar * const input, const int length)
00822 {
00823 static const char * mediaDesc[] = { "screen", "tty", "tv", "projection", "handheld", "print", "braille", "aural", "all", 0 };
00824 const char ** ptr = mediaDesc[0]; int i = 0;
00825 for (; *ptr; ptr++, i++)
00826 {
00827 int len = strlen(*ptr);
00828 if (findInString(input, length, ptr, len))
00829 return alloc.getNew((AttributeValues::MediaDesc *)0, (AttributeValues::MediaDesc::AllowedMedia)i);
00830 }
00831 return InvalidValue;
00832 }
00833
00834
00835 AttributeValue & Validate_MediaDesc (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00836 { return SplitBasedOn(input, length, (AttributeValues::MediaDescs*)0, (AttributeValues::MediaDesc*)0, ',', Val_MediaDesc); }
00837
00838 AttributeValue & Validate_GetPost (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00839 { CheckMinMaxLength(3, 4);
00840 unsigned int value = *reinterpret_cast<const unsigned int* const>(input);
00841 static const unsigned int get = MakeMagic(0, 'g', 'e', 't');
00842 static const unsigned int post = MakeMagic('p', 'o', 's', 't');
00843
00844 if (length == 4 && QCheck(value, post, 32)) return alloc.getNew((AttributeValues::FormMethod *)0, AttributeValues::FormMethod::Post);
00845 if (length == 3 && QCheck(value, get, 24)) return alloc.getNew((AttributeValues::FormMethod *)0, AttributeValues::FormMethod::Get);
00846 return InvalidValue;
00847 }
00848
00849 AttributeValue & Validate_Multiple (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00850 { static const tchar * multiple = "multiple"; return ValidateBooleans(input, length, multiple); }
00851
00852 AttributeValue & Validate_NoHREF (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00853 { static const tchar * nohref = "nohref"; return ValidateBooleans(input, length, nohref); }
00854
00855 AttributeValue & Validate_NoResize (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00856 { static const tchar * noresize = "noresize"; return ValidateBooleans(input, length, noresize); }
00857
00858 AttributeValue & Validate_NoShade (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00859 { static const tchar * noshade = "noshade"; return ValidateBooleans(input, length, noshade); }
00860
00861 AttributeValue & Validate_NoWrap (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00862 { static const tchar * nowrap = "nowrap"; return ValidateBooleans(input, length, nowrap); }
00863
00864
00865 AttributeValue & Validate_Script (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00866 { return alloc.getNew((AttributeValues::Script *)0, input, length); }
00867
00868 AttributeValue & Validate_ReadOnly (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00869 { static const tchar * readonly = "readonly"; return ValidateBooleans(input, length, readonly); }
00870
00871
00872 AttributeValue Val_LinkType (const tchar * const input, const int length)
00873 {
00874 static const char * linkTypes[] = { "alternate" , "stylesheet" , "start" , "next" , "prev" , "contents" , "index" , "glossary" , "copyright" , "chapter" , "section" , "subsection" , "appendix" , "help" , "bookmark", 0 };
00875 const char ** ptr = linkTypes[0]; int i = 0;
00876 for (; *ptr; ptr++, i++)
00877 {
00878 int len = strlen(*ptr);
00879 if (findInString(input, length, ptr, len))
00880 return alloc.getNew((AttributeValues::LinkType *)0, input, length, (AttributeValues::MediaDesc::AllowedMedia)(i+1));
00881 }
00882 return alloc.getNew((AttributeValues::LinkType *)0, input, length);
00883 }
00884
00885 AttributeValue & Validate_LinkTypes (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00886 { return SplitBasedOn(input, length, (AttributeValues::LinkTypes*)0, (AttributeValues::LinkType*)0, ' ', Val_LinkType); }
00887
00888 AttributeValue & Validate_TRules (const AttributeValueAllocator & alloc, const tchar * const input, const int length) { }
00889 { CheckMinMaxLength(3, 6);
00890 unsigned int value = *reinterpret_cast<const unsigned int* const>(input);
00891 static const unsigned int groups = MakeMagic('g', 'r', 'o', 'u');
00892 static const unsigned int rows = MakeMagic('r', 'o', 'w', 's');
00893 static const unsigned int cols = MakeMagic('c', 'o', 'l', 's');
00894 static const unsigned int all = MakeMagic(0, 'a', 'l', 'l');
00895 static const unsigned int none = MakeMagic('n', 'o', 'n', 'e');
00896 if (length == 6 && QCheck(value, groups, 32) && input[4] == 'p' && input[5] == 's') return alloc.getNew((AttributeValues::TRules *)0, AttributeValues::TRules::Groups);
00897 if (length == 4)
00898 {
00899 if (QCheck(value, cols, 32)) return alloc.getNew((AttributeValues::TRules *)0, AttributeValues::TRules::Cols);
00900 if (QCheck(value, rows, 32)) return alloc.getNew((AttributeValues::TRules *)0, AttributeValues::TRules::Rows);
00901 if (QCheck(value, none, 32)) return alloc.getNew((AttributeValues::TRules *)0, AttributeValues::TRules::None);
00902 }
00903 if (length == 3 && QCheck(value, all, 24)) return alloc.getNew((AttributeValues::TRules *)0, AttributeValues::TRules::All);
00904 return InvalidValue;
00905 }
00906
00907 AttributeValue & Validate_Scope (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00908 { CheckMinMaxLength(3, 8);
00909 unsigned int value = *reinterpret_cast<const unsigned int* const>(input);
00910 static const unsigned int roup = MakeMagic('r', 'o', 'u', 'p');
00911 static const unsigned int rowg = MakeMagic('r', 'o', 'w', 'g');
00912 static const unsigned int colg = MakeMagic('c', 'o', 'l', 'g');
00913 static const unsigned int row = MakeMagic(0, 'r', 'o', 'w');
00914 static const unsigned int col = MakeMagic(0, 'c', 'o', 'l');
00915 if (length == 3)
00916 {
00917 if (QCheck(value, col, 24)) return alloc.getNew((AttributeValues::Scope *)0, AttributeValues::Scope::Col);
00918 if (QCheck(value, row, 24)) return alloc.getNew((AttributeValues::Scope *)0, AttributeValues::Scope::Row);
00919 }
00920 if (length == 8)
00921 {
00922 unsigned int value2 = *(reinterpret_cast<const unsigned int* const>(input) + 1);
00923
00924 if (QCheck(value, colg, 32) && QCheck(value2, roup, 32)) return alloc.getNew((AttributeValues::Scope *)0, AttributeValues::Scope::ColGroup);
00925 if (QCheck(value, rowg, 32) && QCheck(value2, roup, 32)) return alloc.getNew((AttributeValues::Scope *)0, AttributeValues::Scope::RowGroup);
00926 }
00927 return InvalidValue;
00928 }
00929
00930 AttributeValue & Validate_YesNoAuto (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00931 { CheckMinMaxLength(2, 4);
00932 unsigned int value = *reinterpret_cast<const unsigned int* const>(input);
00933 static const unsigned int _auto = MakeMagic('a', 'u', 't', 'o');
00934 static const unsigned int yes = MakeMagic(0, 'y', 'e', 's');
00935 static const unsigned int no = MakeMagic(0, 0, 'n', 'o');
00936 if (length == 4 && QCheck(value, _auto, 32)) return alloc.getNew((AttributeValues::Scrolling *)0, AttributeValues::Scrolling::Auto);
00937 if (length == 3 && QCheck(value, yes, 24)) return alloc.getNew((AttributeValues::Scrolling *)0, AttributeValues::Scrolling::Yes);
00938 if (length == 2 && QCheck(value, no, 16)) return alloc.getNew((AttributeValues::Scrolling *)0, AttributeValues::Scrolling::No);
00939 return InvalidValue;
00940 }
00941
00942 AttributeValue & Validate_Selected (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00943 { static const tchar * selected = "selected"; return ValidateBooleans(input, length, selected); }
00944
00945 AttributeValue & Validate_Shape (const AttributeValueAllocator & alloc, const tchar * const input, const int length) { }
00946 { CheckMinMaxLength(4, 7);
00947 unsigned int value = *reinterpret_cast<const unsigned int* const>(input);
00948 static const unsigned int _default = MakeMagic('d', 'e', 'f', 'a');
00949 static const unsigned int poly = MakeMagic('p', 'o', 'l', 'y');
00950 static const unsigned int rect = MakeMagic('r', 'e', 'c', 't');
00951 static const unsigned int circle = MakeMagic('c', 'i', 'r', 'c');
00952 if (length == 4)
00953 {
00954 if (QCheck(value, poly, 32)) return alloc.getNew((AttributeValues::Shape *)0, AttributeValues::Shape::Polygon);
00955 if (QCheck(value, rect, 32)) return alloc.getNew((AttributeValues::Shape *)0, AttributeValues::Shape::Rect);
00956 }
00957 if (length == 6 && QCheck(value, circle, 32) && input[4] == 'l' && input[5] == 'e') return alloc.getNew((AttributeValues::Shape *)0, AttributeValues::Shape::Circle);
00958 if (length == 7 && QCheck(value, _default, 32) && input[4] == 'u' && input[5] == 'l' && input[6] == 't') return alloc.getNew((AttributeValues::Shape *)0, AttributeValues::Shape::Default);
00959 return InvalidValue;
00960 }
00961
00962 AttributeValue & Validate_StyleSheet (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00963 { return alloc.getNew((AttributeValues::Style *)0, input, length); }
00964
00965 AttributeValue & Validate_FrameTarget (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00966 {
00967 if (input[0] == '_')
00968 {
00969 CheckMinMaxLength(3, 6);
00970 unsigned int value = *reinterpret_cast<const unsigned int* const>(input + 1);
00971 static const unsigned int parent = MakeMagic('p', 'a', 'r', 'e');
00972 static const unsigned int top = MakeMagic(0, 't', 'o', 'p');
00973 static const unsigned int blank = MakeMagic('b', 'l', 'a', 'n');
00974 static const unsigned int self = MakeMagic('s', 'e', 'l', 'f');
00975 if (length == 4 && QCheck(value, self, 32)) return alloc.getNew((AttributeValues::FrameTarget *)0, input, length, AttributeValues::FrameTarget::Self);
00976 if (length == 3 && QCheck(value, top, 24)) return alloc.getNew((AttributeValues::FrameTarget *)0, input, length, AttributeValues::FrameTarget::Top);
00977 if (length == 5 && QCheck(value, blank, 32) && input[4] == 'k') return alloc.getNew((AttributeValues::FrameTarget *)0, input, length, AttributeValues::FrameTarget::Blank);
00978 if (length == 6 && QCheck(value, parent, 32) && input[4] == 'n' && input[5] == 't') return alloc.getNew((AttributeValues::FrameTarget *)0, input, length, AttributeValues::FrameTarget::Parent);
00979 }
00980 return alloc.getNew((AttributeValues::FrameTarget *)0, input, length);
00981 }
00982
00983 AttributeValue & Validate_InputType (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
00984 { CheckMinMaxLength(4, 8);
00985 unsigned int value = *reinterpret_cast<const unsigned int* const>(input);
00986 static const unsigned int pass = MakeMagic('p', 'a', 's', 's');
00987 static const unsigned int chec = MakeMagic('c', 'h', 'e', 'c');
00988 static const unsigned int word = MakeMagic('w', 'o', 'r', 'd');
00989 static const unsigned int kbox = MakeMagic('k', 'b', 'o', 'x');
00990 static const unsigned int radio = MakeMagic('r', 'a', 'd', 'i');
00991 static const unsigned int image = MakeMagic('i', 'm', 'a', 'g');
00992 static const unsigned int reset = MakeMagic('r', 'e', 's', 'e');
00993 static const unsigned int submit = MakeMagic('s', 'u', 'b', 'm');
00994 static const unsigned int hidden = MakeMagic('h', 'i', 'd', 'd');
00995 static const unsigned int button = MakeMagic('b', 'u', 't', 't');
00996 static const unsigned int text = MakeMagic('t', 'e', 'x', 't');
00997 static const unsigned int file = MakeMagic('f', 'i', 'l', 'e');
00998 if (length == 8)
00999 {
01000 unsigned int value2 = *(reinterpret_cast<const unsigned int* const>(input) + 1);
01001
01002 if (QCheck(value, pass, 32) && QCheck(value2, word, 32)) return alloc.getNew((AttributeValues::InputType *)0, AttributeValues::InputType::Password);
01003 if (QCheck(value, chec, 32) && QCheck(value2, kbox, 32)) return alloc.getNew((AttributeValues::InputType *)0, AttributeValues::InputType::Checkbox);
01004 }
01005 if (length == 6)
01006 {
01007 if (QCheck(value, submit, 32) && input[4] == 'i' && input[5] == 't') return alloc.getNew((AttributeValues::InputType *)0, AttributeValues::InputType::Submit);
01008 if (QCheck(value, hidden, 32) && input[4] == 'e' && input[5] == 'n') return alloc.getNew((AttributeValues::InputType *)0, AttributeValues::InputType::Hidden);
01009 if (QCheck(value, button, 32) && input[4] == 'o' && input[5] == 'n') return alloc.getNew((AttributeValues::InputType *)0, AttributeValues::InputType::Button);
01010 }
01011 if (length == 5)
01012 {
01013 if (QCheck(value, radio, 32) && input[4] == 'o') return alloc.getNew((AttributeValues::InputType *)0, AttributeValues::InputType::Radio);
01014 if (QCheck(value, image, 32) && input[4] == 'e') return alloc.getNew((AttributeValues::InputType *)0, AttributeValues::InputType::Image);
01015 if (QCheck(value, reset, 32) && input[4] == 't') return alloc.getNew((AttributeValues::InputType *)0, AttributeValues::InputType::Reset);
01016 }
01017 if (length == 4)
01018 {
01019 if (QCheck(value, text, 32)) return alloc.getNew((AttributeValues::InputType *)0, AttributeValues::InputType::Text);
01020 if (QCheck(value, file, 32)) return alloc.getNew((AttributeValues::InputType *)0, AttributeValues::InputType::File);
01021 }
01022 return InvalidValue;
01023 }
01024
01025 AttributeValue & Validate_LIStyle (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
01026 { if (length == 1) return Validate_OLStyle(input, length);
01027 else return Validate_ULStyle(input, length);
01028 }
01029
01030 AttributeValue & Validate_OLStyle (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
01031 { CheckMinMaxLength(1, 1);
01032 switch(input[0])
01033 {
01034 case '1' :
01035 return alloc.getNew((AttributeValues::ListStyle *)0, AttributeValues::ListStyle::One);
01036 case 'a' :
01037 return alloc.getNew((AttributeValues::ListStyle *)0, AttributeValues::ListStyle::LowerAlpha);
01038 case 'A' :
01039 return alloc.getNew((AttributeValues::ListStyle *)0, AttributeValues::ListStyle::UpperAlpha);
01040 case 'i' :
01041 return alloc.getNew((AttributeValues::ListStyle *)0, AttributeValues::ListStyle::LowerRoman);
01042 case 'I' :
01043 return alloc.getNew((AttributeValues::ListStyle *)0, AttributeValues::ListStyle::UpperRoman);
01044 default :
01045 return InvalidValue;
01046 }
01047 }
01048
01049 AttributeValue & Validate_ULStyle (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
01050 { CheckMinMaxLength(4, 6);
01051 unsigned int value = *reinterpret_cast<const unsigned int* const>(input);
01052 static const unsigned int square = MakeMagic('s', 'q', 'u', 'a');
01053 static const unsigned int disc = MakeMagic('d', 'i', 's', 'c');
01054 static const unsigned int circle = MakeMagic('c', 'i', 'r', 'c');
01055 if (length == 6)
01056 {
01057 if (QCheck(value, circle, 32) && input[4] == 'l' && input[5] == 'e') return alloc.getNew((AttributeValues::ListStyle *)0, AttributeValues::ListStyle::Circle);
01058 if (QCheck(value, square, 32) && input[4] == 'r' && input[5] == 'e') return alloc.getNew((AttributeValues::ListStyle *)0, AttributeValues::ListStyle::Square);
01059 }
01060 if (length == 4 && QCheck(value, disc, 32)) return alloc.getNew((AttributeValues::ListStyle *)0, AttributeValues::ListStyle::Disc);
01061 return InvalidValue;
01062 }
01063
01064 AttributeValue & Validate_ButtonSubmitReset (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
01065 { CheckMinMaxLength(5, 6);
01066 unsigned int value = *reinterpret_cast<const unsigned int* const>(input);
01067 static const unsigned int reset = MakeMagic('r', 'e', 's', 'e');
01068 static const unsigned int submit = MakeMagic('s', 'u', 'b', 'm');
01069 static const unsigned int button = MakeMagic('b', 'u', 't', 't');
01070 if (length == 6)
01071 {
01072 if (QCheck(value, submit, 32) && input[4] == 'i' && input[5] == 't') return alloc.getNew((AttributeValues::ButtonType *)0, AttributeValues::ButtonType::Submit);
01073 if (QCheck(value, button, 32) && input[4] == 'o' && input[5] == 'n') return alloc.getNew((AttributeValues::ButtonType *)0, AttributeValues::ButtonType::Button);
01074 }
01075 if (length == 5 && QCheck(value, reset, 32) && input[4] == 't') return alloc.getNew((AttributeValues::ButtonType *)0, AttributeValues::ButtonType::Reset);
01076 return InvalidValue;
01077 }
01078
01079 AttributeValue & Validate_TopMiddleBottomBaseLine (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
01080 { CheckMinMaxLength(3, 8);
01081 unsigned int value = *reinterpret_cast<const unsigned int* const>(input);
01082 static const unsigned int base = MakeMagic('b', 'a', 's', 'e');
01083 static const unsigned int line = MakeMagic('l', 'i', 'n', 'e');
01084 static const unsigned int top = MakeMagic(0, 't', 'o', 'p');
01085 static const unsigned int bottom = MakeMagic('b', 'o', 't', 't');
01086 static const unsigned int middle = MakeMagic('m', 'i', 'd', 'd');
01087 if (length == 6)
01088 {
01089 if (QCheck(value, bottom, 32) && input[4] == 'o' && input[5] == 'm') return alloc.getNew((AttributeValues::Align *)0, AttributeValues::Align::Bottom);
01090 if (QCheck(value, middle, 32) && input[4] == 'l' && input[5] == 'e') return alloc.getNew((AttributeValues::Align *)0, AttributeValues::Align::Middle);
01091 }
01092 if (length == 3 && QCheck(value, top, 24)) return alloc.getNew((AttributeValues::Align *)0, AttributeValues::Align::Top);
01093 if (length == 8)
01094 {
01095 unsigned int value2 = *(reinterpret_cast<const unsigned int* const>(input) + 1);
01096 if (QCheck(value, base, 32) && QCheck(value2, line, 32)) return alloc.getNew((AttributeValues::Align *)0, AttributeValues::Align::BaseLine);
01097 }
01098 return InvalidValue;
01099 }
01100
01101 AttributeValue & Validate_DataRefObject (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
01102 { CheckMinMaxLength(3, 6);
01103 unsigned int value = *reinterpret_cast<const unsigned int* const>(input);
01104 static const unsigned int data = MakeMagic('d', 'a', 't', 'a');
01105 static const unsigned int object = MakeMagic('o', 'b', 'j', 'e');
01106 static const unsigned int ref = MakeMagic(0, 'r', 'e', 'f');
01107 if (length == 6 && QCheck(value, object, 32) && input[4] == 'c' && input[5] == 't') return alloc.getNew((AttributeValues::ValueType *)0, AttributeValues::ValueType::Object);
01108 if (length == 3 && QCheck(value, ref, 24)) return alloc.getNew((AttributeValues::ValueType *)0, AttributeValues::ValueType::Ref);
01109 if (length == 4 && QCheck(value, data, 32)) return alloc.getNew((AttributeValues::ValueType*)0, AttributeValues::ValueType::Data);
01110 return InvalidValue;
01111 }
01112
01113 AttributeValue & Validate_MultiLength (const AttributeValueAllocator & alloc, const tchar * const input, const int length)
01114 { if (input[length-1] == '*') return alloc.getNew((AttributeValues::Length*)0, 0, AttributeValues::Length::Relative);
01115 return Validate_Length(input, length);
01116 }
01117 #undef CheckLength