include/HTMLParser/AttributeValidation.hpp

Go to the documentation of this file.
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                     //TODO : Add rgb(,,) parsing here
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         //TODO: I should parse the style sheet
00297 //            struct Style : public AttributeValue
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             {   // Count the ch to allocate the array
00415                 int len = length;
00416                 // Don't count ch at end, if any
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         // TODO: Allow uppercase version too
00462         AttributeValue & Validate_URI (const AttributeValueAllocator & alloc, const tchar * const input, const int length) 
00463             {   // Based on http://www.ietf.org/rfc/rfc2396.txt
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                 // First loop on data, validate char and determine if URI is absolute or relative
00478                 while (i < length)
00479                 {   // Disallowed characters
00480                     if (input[i] < 0x21 || (unsigned char)input[i] > 0x7F) return InvalidValue;
00481                     if (input[i] == '<' || 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                                 // Read the authority now
00518                                 while (i < length && (isIn(unreserved, input[i]) || input[i] == '%' || isIn(less_reserved, input[i]))) ++i;
00519                                 auth_e = i;
00520                             }
00521 
00522                             // Read the path now if any existing
00523                             if (i < length && input[i] == '/')
00524                             {
00525                                 // Path starting 
00526                                 path_s = i;
00527                                 while (i < length && input[i] != '?' && input[i] != '#') ++i;
00528                                 path_e = i;
00529 
00530                                 // If there is a query read it 
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                             // Read the path now
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                             // No query to read 
00546                         }
00547                         // Go to fragment parsing
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                         // Read the authority now
00556                         while (i < length && (isIn(unreserved, input[i]) || input[i] == '%' || isIn(less_reserved, input[i]))) ++i;
00557                         auth_e = i;
00558 
00559                         // Read the path now if any existing
00560                         if (i < length && input[i] == '/')
00561                         {
00562                             // Path starting 
00563                             path_s = i;
00564                             while (i < length && input[i] != '?' && input[i] != '#') ++i;
00565                             path_e = i;
00566 
00567                             // If there is a query read it 
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                         // Read the path now
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                         // Go to fragment parsing
00589                     }
00590                 }
00591 
00592                 // Parse the fragment
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                 // Check if it is a hex color
00646                 if (input[0] == '#')
00647                     return AttributeValue::Color(&input[1], length);
00648             
00649                 // Then look for defined web colors
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             {   // This is very complex at first, so we will defer the validation, and only accept latin1 and us character set for now
00682                 //TODO : Allow validating all charsets from http://www.iana.org/assignments/character-sets
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         // This is case sensitive
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         // This is case sensitive
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             {   // Based on RFC 1766
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         // This is not in attribute list, and is case sensitive
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         // This is case sensitive
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         //This is case sensitive 
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         // This is not in attribute list
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                 {   // Special target 
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                                                          

(C) An X-Ryl669 project 2007

This document describes Unlimited Zooming Interface source code. UZI stands for Unlimited Zooming Interface, and source code license is