#include "GuiDocument.h"
#include "GuiParserManager.h"
#include "GuiResourceManager.h"
namespace
{
namespace
{
using
namespace
controls
;
using
namespace
collections
;
using
namespace
parsing
;
using
namespace
parsing
::
xml
;
using
namespace
stream
;
using
namespace
filesystem
;
(
const
&
)
{
auto
=
(
).
().
();
if
(
path
!=
L""
)
{
if
(
path
path
.
() -
1
] !=
::
)
{
path
::
;
}
}
return
path
;
}
(
const
&
)
{
return
(
).
();
}
bool
(
const
&
,
&
)
{
::
;
bool
;
return
(
).
ReadAllTextWithEncodingTesting
(
,
encoding
,
bom
);
}
bool
(
const
&
,
&
,
&
)
{
Pair<vint, vint> index = INVLOC.FindFirst(text, L"://", Locale::None);
<
,
>
=
vl
::
::
().
(
,
L"://"
,
::
);
if
(
index
.
!= -
1
)
{
protocol = INVLOC.ToLower(text.Sub(0, index.key));
.
(
index
.
+
index
.
,
.
() -
index
.
-
index
.
);
return
true
;
}
else
{
return
false
;
}
}
(
wchar_t
)
{
if
(
L'0'
<=
&&
<=
L'9'
)
{
return
-
L'0'
;
}
else
if
(
L'A'
<=
&&
<=
L'F'
)
{
return
-
L'A'
+
10
;
}
else
{
return
0
;
}
}
void
(
stream
::
&
,
const
&
)
{
const
wchar_t
*
=
.
();
=
.
() /
2
;
for
(
=
0
;
i
<
count
;
i
++)
{
= (
)(
(
buffer
[
0
]) *
16
+
(
buffer
[
1
]));
buffer
+=
2
;
.
(&
byte
,
1
);
}
}
(
stream
::
&
)
{
stream
::
;
{
stream
::
(
memoryStream
);
;
while
(
.
(&
byte
,
1
) ==
1
)
{
writer
.
(
L"0123456789ABCDEF"
[
byte
/
16
]);
writer
.
(
L"0123456789ABCDEF"
[
byte
%
16
]);
}
}
memoryStream
.
(
0
);
{
stream
::
(
memoryStream
);
return
reader
.
();
}
}
::
;
::
;
::
;
::
;
::
;
::
;
::
;
::
;
::
;
::
;
class
{
public
:
<
,
>
;
<
>
;
void
()
{
::
=
::
(
L"set"
);
::
=
::
(
L"_"
);
::
=
::
(
L"ref"
);
::
=
::
(
L"bind"
);
::
=
::
(
L"format"
);
::
=
::
(
L"str"
);
::
=
::
(
L"eval"
);
::
=
::
(
L"uri"
);
::
=
::
(
L"ControlTemplate"
);
}
}*
=
0
;
::
(
const
&
)
{
;
if
(
L""
)
{
=
globalStringKeyManager
->
.
().
(
);
if
(
index
== -
1
)
{
key
.
=
globalStringKeyManager
->
.
(
);
globalStringKeyManager
->
.
(
,
key
.
);
}
else
{
key
.
=
globalStringKeyManager
->
.
()
index
];
}
}
return
key
;
}
::
()
const
{
return
;
}
::
()
const
{
return
*
this
==
::
?
L""
:
globalStringKeyManager
->
];
}
::
()
:frameIndex(-
1
)
{
}
::
(
<
>
,
)
: image(
)
, frameIndex(
)
{
}
::
()
{
}
<
>
::
()
{
return
;
}
::
()
{
return
;
}
::
()
{
}
::
(
const
&
)
:text(
)
{
}
::
()
{
return
;
}
::
()
:parent(
0
)
{
}
::
()
{
}
const
&
::
()
{
return
;
}
::
()
{
auto
=
;
auto
=
;
while
(
current
&&
current
->
())
{
resourcePath
=
current
->
() +
L"/"
+
resourcePath
;
current
=
current
->
();
}
return
resourcePath
;
}
const
&
::
()
{
return
;
}
const
&
::
()
{
return
;
}
void
::
(
const
&
,
const
&
)
{
;
;
}
*
::
()
{
return
;
}
::
(
const
&
,
const
&
)
:resourcePath(
)
, filePath(
)
{
}
::
(
<
>
)
{
if
(
)
{
();
auto
=
.
();
while
(
current
)
{
if
(
current
->
()
L""
)
{
current
->
();
break
;
}
current
=
current
->
();
}
}
}
::
(
,
parsing
::
)
:originalLocation(
)
, row(
.
)
, column(
.
)
{
}
::
(
,
const
&
)
:location(
.
)
, position(
)
, message(
)
{
}
::
(
,
const
&
)
:location(
)
, position(
, {})
, message(
)
{
}
::
(
,
,
const
&
)
:location(
)
, position(
)
, message(
)
{
}
template
<
typename
>
void
(
::
&
,
collections
::
<
<
parsing
::
>>&
,
,
const
&
)
{
if
(
.
<
0
||
.
<
0
)
{
.
=
0
;
.
=
0
;
}
FOREACH(Ptr<ParsingError>, error, parsingErrors)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
error
);)
{
auto
=
error
.
;
if
(
pos
.
<
0
||
pos
.
<
0
)
{
pos
{
.
,
.
};
}
else
{
if
(
pos
.
==
0
)
{
pos
.
+=
.
;
}
pos
.
+=
.
;
}
.
(
({
.
,
pos
},
error
));
}
}
void
::
(
,
::
&
,
collections
::
<
<
parsing
::
>>&
)
{
(
,
,
, {
,{
0
,
0
} });
}
void
::
(
,
::
&
,
collections
::
<
<
parsing
::
>>&
,
parsing
::
)
{
(
,
,
, {
,
});
}
void
::
(
,
::
&
,
collections
::
<
<
parsing
::
>>&
,
)
{
(
,
,
, [&](
,
const
&
)
{
return
(
,
pos
,
message
);
});
}
void
::
(
&
,
collections
::
<
>&
,
const
&
)
{
if
(
.
() ==
0
)
return
;
(&
0
],
.
(), [](
const
&
,
const
&
)
{
=
0
;
if
(
result
==
0
)
result
=
::
(
a
.
.
,
b
.
.
);
if
(
result
==
0
)
result
=
::
(
a
.
.
,
b
.
.
);
if
(
result
==
0
)
result
=
::
(
a
.
.
.
,
b
.
.
.
);
if
(
result
==
0
)
result
=
::
(
a
.
.
.
,
b
.
.
.
);
if
(
result
==
0
)
result
=
a
.
.
-
b
.
.
;
if
(
result
==
0
)
result
=
a
.
.
-
b
.
.
;
return
result
;
});
FOREACH_INDEXER(GuiResourceError, error, index, errors)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
if
(
bool
=
true
)
for
(
=
0
;
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
;
__foreach_iterator__
.
(
error
);
index
++)
{
bool
=
index
==
0
;
if
(
index
>
0
)
{
auto
=
index
-
1
];
if
(
error
.
previousError
.
||
error
.
.
!=
previousError
.
.
)
{
needHeader
=
true
;
}
}
#define CONVERT_FILEPATH(FILEPATH) (workingDirectory == L"" ? FILEPATH : filesystem::FilePath(workingDirectory).GetRelativePathFor(FILEPATH))
#define CONVERT_LOCATION(LOCATION) (LOCATION).resourcePath + L" # " + CONVERT_FILEPATH((LOCATION).filePath)
if
(
needHeader
)
{
output.Add(CONVERT_LOCATION(error.location));
.
((
error
.
).
+
L" # "
+ (
L""
? (
error
.
).
:
filesystem
::
(
).
((
error
.
).
)));
if
(
error
.
error
.
.
)
{
output.Add(L" Original: " + CONVERT_LOCATION(error.position.originalLocation));
.
(
L" Original: "
+ (
error
.
.
).
+
L" # "
+ (
L""
? (
error
.
.
).
:
filesystem
::
(
).
((
error
.
.
).
)));
}
}
=
L"Failed to load file \""
;
=
L"\"."
;
if (INVLOC.StartsWith(error.message, prefix, Locale::Normalization::None) && INVLOC.EndsWith(error.message, postfix, Locale::Normalization::None))
if
(
vl
::
::
().
(
error
.
,
prefix
,
::
::
) &&
vl
::
::
().
(
error
.
,
postfix
,
::
::
))
{
auto
=
error
.
.
(
prefix
.
(),
error
.
.
() -
prefix
.
() -
postfix
.
());
path = CONVERT_FILEPATH(path);
path
(
L""
?
path
:
filesystem
::
(
).
(
path
));
error
.
=
prefix
+
path
+
postfix
;
}
auto
=
error
.
.
;
if
(
row
>=
0
)
row
++;
auto
=
error
.
.
;
if
(
column
>=
0
)
column
++;
.
(
L"("
+
(
row
) +
L", "
+
(
column
) +
L"): "
+
error
.
);
#undef CONVERT_FILEPATH
#undef CONVERT_LOCATION
}
}
::
()
{
}
::
()
{
}
const
&
::
()
{
return
;
}
<
>
::
()
{
return
;
}
void
::
(
const
&
,
<
>
)
{
;
;
}
<
>
::
()
{
return
.
<
>();
}
<
parsing
::
xml
::
>
::
()
{
return
.
<
>();
}
<
>
::
()
{
return
.
<
>();
}
<
>
::
()
{
return
.
<
>();
}
void
::
LoadResourceFolderFromXml
(
&
,
const
&
,
<
parsing
::
xml
::
>
,
::
&
)
{
();
();
FOREACH(Ptr<XmlElement>, element, XmlGetElements(folderXml))
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
(
));
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
element
);)
{
;
if
(
<
>
=
(
element
,
L"name"
))
{
name
nameAtt
.
;
}
if
(
element
.
==
L"Folder"
)
{
if
(
name
==
L""
)
{
.
(
({ {
this
},
element
.
},
L"A resource folder should have a name."
));
}
else
{
<
>
=
new
;
if
(
(
name
,
folder
))
{
=
;
<
>
=
element
;
if
(
<
>
=
(
element
,
L"content"
))
{
if
(
contentAtt
.
==
L"Link"
)
{
auto
=
(
element
);
auto
=
fileContentPath
;
folder
(
fileContentPath
,
fileAbsolutePath
);
;
if
(
(
fileAbsolutePath
,
text
))
{
if
(
auto
=
()->
<
>(
L"XML"
))
{
if
(
auto
=
parser
->Parse({
::
,
fileAbsolutePath
},
text
,
))
{
newContainingFolder
(
fileAbsolutePath
);
newFolderXml
=
xml
->rootElement;
}
}
}
else
{
.
(
({ {
this
},
element
.
},
L"Failed to load file \""
+
fileAbsolutePath
+
L"\"."
));
}
}
else
if
(
contentAtt
.
==
L"Import"
)
{
auto
=
(
element
);
folder
(
importUri
, { {
this
},
element
.
},
);
}
else
{
.
(
({ {
this
},
element
.
},
L"Folder's content attributes can only be \"Link\"."
));
}
}
if
(
folder
()
L""
)
{
folder
LoadResourceFolderFromXml
(
,
newContainingFolder
,
newFolderXml
,
);
}
}
else
{
.
(
({ {
this
},
element
.
},
L"Duplicated resource folder name \""
+
name
+
L"\"."
));
}
}
}
else
if
(
element
.
.
() <=
3
||
element
.
.
(
0
,
4
) !=
L"ref."
)
{
;
;
if
(
<
>
=
(
element
,
L"content"
))
{
if
(
contentAtt
.
==
L"File"
)
{
fileContentPath
(
element
);
fileAbsolutePath
fileContentPath
;
if
(
name
==
L""
)
{
name
(
fileAbsolutePath
);
}
}
else
{
.
(
({ {
this
},
element
.
},
L"File's content attributes can only be \"File\"."
));
}
}
<
>
=
new
;
if
(
(
name
,
item
))
{
=
element
.
;
*
=
GetResourceResolverManager
()->
(
type
);
*
=
typeResolver
;
if
(
typeResolver
)
{
if
(!
typeResolver
->
())
{
=
typeResolver
->
()->
();
preloadResolver
=
GetResourceResolverManager
()->
(
preloadType
);
if
(!
preloadResolver
)
{
.
(
({ {
this
},
element
.
},
L"[INTERNAL-ERROR] Unknown resource resolver \""
+
preloadType
+
L"\" of resource type \""
+
type
+
L"\"."
));
}
}
}
else
{
.
(
({ {
this
},
element
.
},
L"Unknown resource type \""
+
type
+
L"\"."
));
}
if
(
typeResolver
&&
preloadResolver
)
{
if
(
auto
=
preloadResolver
->
())
{
{
<
>
;
if
(
fileAbsolutePath
==
L""
)
{
resource
directLoad
->
(
item
,
element
,
);
}
else
{
item
(
fileContentPath
,
fileAbsolutePath
);
resource
directLoad
->
(
item
,
fileAbsolutePath
,
);
}
item
(
preloadResolver
->
(),
resource
);
}
if
(
typeResolver
!=
preloadResolver
)
{
if
(
auto
=
typeResolver
->
())
{
if
(
indirectLoad
->
())
{
;
delayLoading
.
type
;
delayLoading
.
;
delayLoading
.
item
;
.
(
delayLoading
);
}
else
if
(
item
())
{
auto
=
indirectLoad
->
(
item
,
0
,
);
item
(
typeResolver
->
(),
resource
);
}
}
else
{
item
(
typeResolver
->
(),
nullptr
);
.
(
({ {
this
},
element
.
},
L"[INTERNAL-ERROR] Resource type \""
+
typeResolver
->
() +
L"\" is not a indirect load resource type."
)); }
}
}
else
{
.
(
({ {
this
},
element
.
},
L"[INTERNAL-ERROR] Resource type \""
+
preloadResolver
->
() +
L"\" is not a direct load resource type."
));
}
}
if
(!
item
())
{
(
name
);
}
}
else
{
.
(
({ {
this
},
element
.
},
L"Duplicated resource item name \""
+
name
+
L"\"."
));
}
}
}
}
void
::
(
<
parsing
::
xml
::
>
)
{
FOREACH(Ptr<GuiResourceItem>, item, items.Values())
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
.
());
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
item
);)
{
auto
=
GetResourceResolverManager
()->
(
item
());
if
(
resolver
->
())
{
auto
=
<
>();
attName
.
=
L"name"
;
attName
.
item
();
if
(
item
()
L""
)
{
<
>
;
if
(
auto
=
resolver
->
())
{
xmlElement
directLoad
->
(
item
,
item
());
}
else
if
(
auto
=
resolver
->
())
{
if
(
auto
=
GetResourceResolverManager
()->
(
indirectLoad
->
()))
{
if
(
auto
=
preloadResolver
->
())
{
if
(
auto
=
indirectLoad
->
(
item
,
item
()))
{
xmlElement
directLoad
->
(
item
,
resource
);
xmlElement
.
resolver
->
();
}
}
}
}
if
(
xmlElement
)
{
xmlElement
.
(
attName
);
.
(
xmlElement
);
}
}
else
{
auto
=
<
>();
xmlElement
.
item
();
.
(
xmlElement
);
auto
=
<
>();
attContent
.
=
L"content"
;
attContent
.
=
L"File"
;
xmlElement
.
(
attContent
);
auto
=
<
>();
xmlText
.
item
();
xmlElement
.
(
xmlText
);
}
}
}
FOREACH(Ptr<GuiResourceFolder>, folder, folders.Values())
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
.
());
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
folder
);)
{
auto
=
<
>();
attName
.
=
L"name"
;
attName
.
folder
();
auto
=
<
>();
xmlFolder
.
=
L"Folder"
;
xmlFolder
.
(
attName
);
.
(
xmlFolder
);
if
(
folder
()
L""
)
{
auto
=
<
>();
attContent
.
=
L"content"
;
attContent
.
=
L"Import"
;
xmlFolder
.
(
attContent
);
auto
=
<
>();
xmlText
.
folder
();
xmlFolder
.
(
xmlText
);
}
else
if
(
folder
()
L""
)
{
auto
=
<
>();
attContent
.
=
L"content"
;
attContent
.
=
L"Link"
;
xmlFolder
.
(
attContent
);
auto
=
<
>();
xmlText
.
folder
();
xmlFolder
.
(
xmlText
);
}
else
{
folder
(
xmlFolder
);
}
}
}
void
::
(
collections
::
<
>&
)
{
if
(
!=
L""
)
return
;
FOREACH(Ptr<GuiResourceItem>, item, items.Values())
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
.
());
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
item
);)
{
if
(!
.
(
item
()))
{
.
(
item
());
}
}
FOREACH(Ptr<GuiResourceFolder>, folder, folders.Values())
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
.
());
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
folder
);)
{
folder
(
);
}
}
void
::
LoadResourceFolderFromBinary
(
&
,
stream
::
internal
::
&
,
collections
::
<
>&
,
::
&
)
{
=
0
;
count
;
for
(
=
0
;
i
<
count
;
i
++)
{
=
0
;
;
typeName
name
;
auto
=
GetResourceResolverManager
()->
(
typeName
]);
<
>
=
new
;
if
(
(
name
,
item
))
{
=
typeName
];
*
=
GetResourceResolverManager
()->
(
type
);
*
=
typeResolver
;
if
(
typeResolver
)
{
if
(!
typeResolver
->
())
{
=
typeResolver
->
()->
();
if
(
preloadType
!=
L""
)
{
preloadResolver
=
GetResourceResolverManager
()->
(
preloadType
);
if
(!
preloadResolver
)
{
.
(
({
item
},
L"[INTERNAL-ERROR] Unknown resource resolver \""
+
preloadType
+
L"\" of resource type \""
+
type
+
L"\"."
));
}
}
}
}
else
{
.
(
({
item
},
L"[BINARY] Unknown resource type \""
+
type
+
L"\"."
));
}
if
(
typeResolver
&&
preloadResolver
)
{
if
(
auto
=
preloadResolver
->
())
{
{
auto
=
directLoad
->
ResolveResourcePrecompiled
(
item
,
.
,
);
item
(
preloadResolver
->
(),
resource
);
}
if
(
typeResolver
!=
preloadResolver
)
{
if
(
auto
=
typeResolver
->
())
{
if
(
indirectLoad
->
())
{
;
delayLoading
.
type
;
delayLoading
.
item
;
.
(
delayLoading
);
}
else
if
(
item
())
{
auto
=
indirectLoad
->
(
item
,
nullptr
,
);
item
(
typeResolver
->
(),
resource
);
}
}
else
{
item
(
typeResolver
->
(),
nullptr
);
.
(
({
item
},
L"[INTERNAL-ERROR] Resource type \""
+
typeResolver
->
() +
L"\" is not a indirect load resource type."
));
}
}
}
else
{
.
(
({
item
},
L"[INTERNAL-ERROR] Resource type \""
+
preloadResolver
->
() +
L"\" is not a direct load resource type."
));
}
}
if
(!
item
())
{
(
name
);
}
}
else
{
.
(
({
this
},
L"[BINARY] Duplicated resource item name \""
+
name
+
L"\"."
));
}
}
count
;
for
(
=
0
;
i
<
count
;
i
++)
{
,
;
name
importUri
;
auto
=
<
>();
if
(
importUri
==
L""
)
{
folder
LoadResourceFolderFromBinary
(
,
,
,
);
}
else
{
folder
(
importUri
, { {
this
},{
0
,
0
} },
);
}
(
name
,
folder
);
}
}
void
::
SaveResourceFolderToBinary
(
stream
::
internal
::
&
,
collections
::
<
>&
)
{
typedef
<
,
,
IGuiResourceTypeResolver_DirectLoadStream
*,
<
>,
<
>>
;
<
>
;
FOREACH(Ptr<GuiResourceItem>, item, items.Values())
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
.
());
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
item
);)
{
auto
=
GetResourceResolverManager
()->
(
item
());
if
(
resolver
->
())
{
=
.
(
item
());
=
item
();
if
(
auto
=
resolver
->
())
{
itemTuples
.
(
(
typeName
,
name
,
directLoad
,
item
,
item
()));
}
else
if
(
auto
=
resolver
->
())
{
if
(
auto
=
GetResourceResolverManager
()->
(
indirectLoad
->
()))
{
if
(
auto
=
preloadResolver
->
())
{
if
(
auto
=
indirectLoad
->
(
item
,
item
()))
{
itemTuples
.
(
(
typeName
,
name
,
directLoad
,
item
,
resource
));
}
}
}
}
}
}
=
itemTuples
.
();
count
;
FOREACH(ItemTuple, item, itemTuples)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
>&
= ::
vl
::
collections
::
(
itemTuples
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
;
__foreach_iterator__
.
(
item
);)
{
=
item
.f0;
=
item
.f1;
typeName
name
;
auto
=
item
.f2;
auto
=
item
.f3;
auto
=
item
.f4;
directLoad
->SerializePrecompiled(
resource
,
content
,
.
);
}
count
=
.
();
count
;
FOREACH(Ptr<GuiResourceFolder>, folder, folders.Values())
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
.
());
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
folder
);)
{
=
folder
();
=
folder
();
name
importUri
;
if
(
importUri
==
L""
)
{
folder
SaveResourceFolderToBinary
(
,
);
}
}
}
void
::
(
GuiResourcePrecompileContext
&
,
IGuiResourcePrecompileCallback
*
,
::
&
)
{
if
(
!=
L""
)
return
;
FOREACH(Ptr<GuiResourceItem>, item, items.Values())
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
.
());
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
item
);)
{
auto
=
GetResourceResolverManager
()->
(
item
());
if
(
auto
=
typeResolver
->
())
{
if
(
precompile
->
(
.
) ==
IGuiResourceTypeResolver_Precompile
::
)
{
if
(
)
{
->
(
.
,
item
);
}
precompile
->
(
item
,
,
);
}
}
}
FOREACH(Ptr<GuiResourceFolder>, folder, folders.Values())
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
.
());
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
folder
);)
{
folder
(
,
,
);
}
}
void
::
(
GuiResourceInitializeContext
&
,
::
&
)
{
if
(
!=
L""
)
return
;
FOREACH(Ptr<GuiResourceItem>, item, items.Values())
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
.
());
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
item
);)
{
auto
=
GetResourceResolverManager
()->
(
item
());
if
(
auto
=
typeResolver
->
())
{
initialize
->
(
item
,
,
);
}
}
FOREACH(Ptr<GuiResourceFolder>, folder, folders.Values())
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
.
());
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
folder
);)
{
folder
(
,
);
}
}
void
::
(
const
&
,
,
::
&
)
{
(
);
if
(
.
() ==
0
||
.
() -
1
] !=
L'/'
)
{
.
(
(
,
L"Path of imported folder should ends with L\"/\"."
));
}
else
{
,
;
if
(
(
,
protocol
,
path
))
{
if
(
protocol
==
L"import-res"
)
{
auto
=
GetResourceResolverManager
()->
(
protocol
);
auto
=
factory
->
(
nullptr
,
L""
);
if
(
auto
=
resolver
->ResolveResource(
path
).Cast<
>())
{
(
,
sourceFolder
->items);
(
,
sourceFolder
->folders);
}
else
{
.
(
(
,
L"Path of imported folder does not exist: \""
+
+
L"\"."
));
}
}
else
{
.
(
(
,
L"Path of imported folder should begin with \"import-res://\"."
));
}
}
else
{
.
(
(
,
L"Invalid path of imported folder : \""
+
+
L"\"."
));
}
}
}
::
()
{
}
::
()
{
}
const
&
::
()
{
return
;
}
void
::
(
const
&
)
{
;
}
const
::
&
::
()
{
return
.
();
}
<
>
::
(
const
&
)
{
=
.
().
(
);
return
index
== -
1
?
nullptr
:
.
().
(
index
);
}
bool
::
(
const
&
,
<
>
)
{
if
(
() !=
0
||
.
().
(
))
return
false
;
.
(
,
);
=
this
;
;
return
true
;
}
<
>
::
(
const
&
)
{
<
>
=
(
);
if
(!
item
)
return
0
;
.
(
);
item
=
nullptr
;
item
=
L""
;
return
item
;
}
void
::
()
{
.
();
}
const
::
&
::
()
{
return
.
();
}
<
>
::
(
const
&
)
{
=
.
().
(
);
return
index
== -
1
?
nullptr
:
.
().
(
index
);
}
bool
::
(
const
&
,
<
>
)
{
if
(
() !=
0
||
.
().
(
))
return
false
;
.
(
,
);
=
this
;
;
return
true
;
}
<
>
::
(
const
&
)
{
<
>
=
(
);
if
(!
folder
)
return
0
;
.
(
);
folder
=
nullptr
;
folder
=
L""
;
return
folder
;
}
void
::
()
{
.
();
}
<
>
::
(
const
&
)
{
const
wchar_t
*
=
.
();
const
wchar_t
*
=
(
buffer
,
L'\\'
);
if
(!
index
)
index
=
(
buffer
,
'/'
);
if
(
index
)
{
=
.
(
0
,
index
-
buffer
);
<
>
=
(
name
);
if
(
folder
)
{
=
index
-
buffer
+
1
;
return
folder
(
.
(
start
,
.
()-
start
));
}
}
else
{
<
>
=
(
);
if
(
item
)
{
return
item
();
}
}
return
0
;
}
<
>
::
(
const
&
)
{
const
wchar_t
*
=
.
();
const
wchar_t
*
=
(
buffer
,
L'\\'
);
if
(!
index
)
index
=
(
buffer
,
'/'
);
if
(!
index
)
return
0
;
=
.
(
0
,
index
-
buffer
);
<
>
=
(
name
);
if
(
index
-
buffer
==
.
()-
1
)
{
return
folder
;
}
if
(
folder
)
{
=
index
-
buffer
+
1
;
return
folder
(
.
(
start
,
.
()-
start
));
}
return
0
;
}
bool
::
(
const
&
,
const
&
,
<
>
)
{
const
wchar_t
*
=
.
();
const
wchar_t
*
=
(
buffer
,
L'\\'
);
if
(!
index
)
index
=
(
buffer
,
'/'
);
if
(
index
)
{
=
.
(
0
,
index
-
buffer
);
<
>
=
(
name
);
if
(!
folder
)
{
folder
new
;
(
name
,
folder
);
}
=
index
-
buffer
+
1
;
return
folder
(
.
(
start
,
.
() -
start
),
,
);
}
else
{
if
(
(
))
{
return
false
;
}
auto
=
new
;
item
->
(
,
);
return
(
,
item
);
}
}
void
::
(
<
parsing
::
xml
::
>
,
,
::
&
)
{
auto
=
(
,
L"Name"
);
auto
=
(
,
L"Version"
);
if
(!
attrName
|| !
attrVersion
)
{
.
(
(
,
L"[INTERNAL-ERROR] Resource metadata lacks of Name or Version attribute."
));
return
;
}
=
attrName
->value.value;
=
attrVersion
->value.value;
.
();
if
(
auto
=
(
,
L"Dependencies"
))
{
FOREACH(Ptr<XmlElement>, xmlDep, XmlGetElements(xmlDeps, L"Resource"))
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
(
xmlDeps
,
L"Resource"
));
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
xmlDep
);)
{
auto
=
(
xmlDep
,
L"Name"
);
if
(!
attrDep
)
{
.
(
(
,
L"[INTERNAL-ERROR] Resource dependency lacks of Name attribute."
));
}
.
(
attrDep
->value.value);
}
}
}
<
parsing
::
xml
::
>
::
()
{
auto
=
<
>();
root
.
=
L"ResourceMetadata"
;
{
auto
=
<
>();
attr
.
=
L"Name"
;
attr
.
;
root
.
(
attr
);
}
{
auto
=
<
>();
attr
.
=
L"Version"
;
attr
.
;
root
.
(
attr
);
}
{
auto
=
<
>();
xmlDeps
.
=
L"Dependencies"
;
root
.
(
xmlDeps
);
FOREACH(WString, dep, dependencies)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
;
__foreach_iterator__
.
(
dep
);)
{
auto
=
<
>();
xmlDep
.
=
L"Resource"
;
xmlDeps
.
(
xmlDep
);
{
auto
=
<
>();
attr
.
=
L"Name"
;
attr
.
dep
;
xmlDep
.
(
attr
);
}
}
}
auto
=
<
>();
doc
root
;
return
doc
;
}
const
wchar_t
*
::
=
L"1.0"
;
void
::
(
<
>
,
&
,
::
&
)
{
FOREACH(DelayLoading, delay, delayLoadings)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
;
__foreach_iterator__
.
(
delay
);)
{
=
delay
.
;
=
delay
.
;
<
>
=
delay
.
;
if
(
auto
=
GetResourceResolverManager
()->
(
type
))
{
if
(
auto
=
typeResolver
->
())
{
if
(
item
())
{
<
>
=
new
(
,
folder
);
<
>
=
indirectLoad
->
(
item
,
pathResolver
,
);
if
(
resource
)
{
item
(
typeResolver
->
(),
resource
);
}
}
}
else
{
.
(
({
item
},
L"[INTERNAL-ERROR] Resource type \""
+
type
+
L"\" is not a indirect load resource type."
));
}
}
else
{
.
(
({
item
},
L"[INTERNAL-ERROR] Unknown resource type \""
+
type
+
L"\"."
));
}
}
}
::
()
{
<
>();
=
;
}
::
()
{
}
<
>
::
()
{
return
;
}
::
()
{
return
;
}
<
>
::
(
<
parsing
::
xml
::
>
,
const
&
,
const
&
,
::
&
)
{
<
>
=
new
;
resource
(
,
);
resource
;
;
resource
LoadResourceFolderFromXml
(
delayLoadings
,
resource
,
,
);
(
resource
,
delayLoadings
,
);
return
resource
;
}
<
>
::
(
const
&
,
::
&
)
{
<
>
;
if
(
auto
=
()->
<
>(
L"XML"
))
{
;
if
(
(
,
text
))
{
xml
=
parser
->Parse({
::
,
},
text
,
);
}
else
{
.
(
({
::
,
},
L"Failed to load file \""
+
+
L"\"."
));
}
}
if
(
xml
)
{
return
(
xml
,
,
(
),
);
}
return
0
;
}
<
parsing
::
xml
::
>
::
()
{
auto
=
<
>();
xmlRoot
.
=
L"Resource"
;
(
xmlRoot
);
auto
=
<
>();
doc
xmlRoot
;
return
doc
;
}
<
>
::
(
stream
::
&
,
::
&
)
{
stream
::
internal
::
(
);
auto
=
<
>();
{
;
reader
metadata
;
auto
=
()->
<
>(
L"XML"
);
auto
=
parser
->Parse({
resource
},
metadata
,
);
if
(!
xmlMetadata
)
return
nullptr
;
resource
(
xmlMetadata
, {
resource
},
);
if
(
.
() !=
0
)
return
nullptr
;
if
(
resource
!=
)
{
.
(
({
resource
},
L"Only resource binary of version \""
+
(
) +
L"\" is accepted. Please recompile the resource before loading it."
));
return
nullptr
;
}
}
<
>
;
reader
typeNames
;
;
resource
LoadResourceFolderFromBinary
(
delayLoadings
,
reader
,
typeNames
,
);
(
resource
,
delayLoadings
,
);
return
resource
;
}
<
>
::
(
stream
::
&
)
{
::
;
auto
=
(
,
errors
);
CHECK_ERROR(errors.Count() == 0, L"GuiResource::LoadPrecompiledBinary(IStream&)#There are errors.");
do
{
if
(!(
errors
.
() ==
0
))
throw
(
L"GuiResource::LoadPrecompiledBinary(IStream&)#There are errors."
);}
while
(
0
);
return
resource
;
}
void
::
(
stream
::
&
)
{
stream
::
internal
::
(
);
{
auto
=
();
=
([&](
&
)
{
(
xmlMetadata
,
writer
);
});
writer
xml
;
}
<
>
;
(
typeNames
);
writer
typeNames
;
SaveResourceFolderToBinary
(
writer
,
typeNames
);
}
<
>
::
(
IGuiResourcePrecompileCallback
*
,
::
&
)
{
if
(
(
L"Precompiled"
))
{
.
(
({
this
},
L"A precompiled resource cannot be compiled again."
));
return
nullptr
;
}
GuiResourcePrecompileContext
;
context
.
=
?
->
() :
nullptr
;
context
.
=
this
;
context
.
new
(
this
,
);
context
.
new
;
auto
=
GetResourceResolverManager
();
=
manager
->
GetMaxPrecompilePassIndex
();
<
>
;
for
(
=
0
;
i
<=
maxPass
;
i
++)
{
context
.
=
i
;
{
manager
->
GetPerResourceResolverNames
(
i
,
resolvers
);
if
(
resolvers
.
() >
0
)
{
(
context
,
,
);
}
}
{
manager
->
(
i
,
resolvers
);
if
(
resolvers
.
() >
0
)
{
if
(
)
{
->
(
i
);
}
FOREACH(WString, name, resolvers)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
>&
= ::
vl
::
collections
::
(
resolvers
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
;
__foreach_iterator__
.
(
name
);)
{
auto
=
manager
->
(
name
);
resolver
->
()->
(
context
,
);
}
}
}
if
(
.
() >
0
)
{
return
context
.
;
}
}
(
L"Precompiled"
,
context
.
);
return
context
.
;
}
void
::
(
,
::
&
)
{
auto
=
(
L"Precompiled"
);
if
(!
precompiledFolder
)
{
CHECK_FAIL(L"GuiResource::Initialize()#Cannot initialize a non-precompiled resource.");
do
{
throw
(
L"GuiResource::Initialize()#Cannot initialize a non-precompiled resource."
);}
while
(
0
);
return
;
}
GuiResourceInitializeContext
;
context
.
=
this
;
context
.
new
(
this
,
);
context
.
=
precompiledFolder
;
context
.
=
;
=
GetResourceResolverManager
()->
GetMaxInitializePassIndex
();
for
(
=
0
;
i
<=
maxPass
;
i
++)
{
context
.
=
i
;
(
context
,
);
}
}
<
>
::
(
const
&
)
{
<
>
=
(
).
<
>();
if
(!
result
)
throw
(
L"Path not exists."
,
L"GuiResource::GetDocumentByPath"
,
L"path"
);
return
result
;
}
<
>
::
(
const
&
)
{
<
>
=
(
).
<
>();
if
(!
result
)
throw
(
L"Path not exists."
,
L"GuiResource::GetImageByPath"
,
L"path"
);
return
result
;
}
<
parsing
::
xml
::
>
::
(
const
&
)
{
<
>
=
(
).
<
>();
if
(!
result
)
throw
(
L"Path not exists."
,
L"GuiResource::GetXmlByPath"
,
L"path"
);
return
result
;
}
::
(
const
&
)
{
<
<
>>
=
(
).
<
<
>>();
if
(!
result
)
throw
(
L"Path not exists."
,
L"GuiResource::GetStringByPath"
,
L"path"
);
return
result
();
}
::
(
<
>
,
const
&
)
:resource(
)
,workingDirectory(
)
{
}
::
()
{
}
<
>
::
(
const
&
,
const
&
)
{
<
>
;
=
.
().
(
);
if
(
index
==-
1
)
{
IGuiResourcePathResolverFactory
*
=
GetResourceResolverManager
()->
(
);
if
(
factory
)
{
resolver
factory
->
(
,
);
}
.
(
,
resolver
);
}
else
{
resolver
.
()
index
];
}
if
(
resolver
)
{
return
resolver
(
);
}
else
{
return
0
;
}
}
class
GuiResourcePathResResolver
:
public
,
public
{
protected
:
<
>
;
public
:
GuiResourcePathResResolver
(
<
>
)
:resource(
)
{
}
<
>
(
const
&
)
{
if
(
)
{
if
(
.
() >
0
)
{
switch
(
.
() -
1
])
{
case
L'\\'
:
case
L'/'
:
return
(
);
default
:
return
(
);
}
}
}
return
nullptr
;
}
class
:
public
,
public
IGuiResourcePathResolverFactory
{
public
:
()
override
{
return
L"res"
;
}
<
>
(
<
>
,
const
&
)
override
{
return
new
GuiResourcePathResResolver
(
);
}
};
};
class
GuiImportResourcePathResResolver
:
public
,
public
{
public
:
GuiImportResourcePathResResolver
()
{
}
<
>
(
const
&
)
{
const
wchar_t
*
=
.
();
const
wchar_t
*
=
(
buffer
,
L'\\'
);
const
wchar_t
*
=
(
buffer
,
L'/'
);
const
wchar_t
*
=
d1
==
nullptr
&&
d2
==
nullptr
?
nullptr
:
d1
==
nullptr
?
d2
:
d2
==
nullptr
?
d1
:
d1
<
d2
?
d1
:
d2
;
if
(!
d
)
return
nullptr
;
(
buffer
,
d
-
buffer
);
(
.
(
.
() -
resourceName
.
() -
1
));
if
(
auto
=
()->
(
resourceName
))
{
switch
(
.
() -
1
])
{
case
L'\\'
:
case
L'/'
:
return
resource
(
resourcePath
);
default
:
return
resource
(
resourcePath
);
}
}
return
nullptr
;
}
class
:
public
,
public
IGuiResourcePathResolverFactory
{
public
:
()
override
{
return
L"import-res"
;
}
<
>
(
<
>
,
const
&
)
override
{
return
new
GuiImportResourcePathResResolver
;
}
};
};
IGuiResourceResolverManager
*
=
0
;
IGuiResourceResolverManager
*
GetResourceResolverManager
()
{
return
resourceResolverManager
;
}
class
GuiResourceResolverManager
:
public
,
public
IGuiResourceResolverManager
,
public
{
typedef
<
,
<
IGuiResourcePathResolverFactory
>>
;
typedef
<
,
<
>>
;
typedef
<
,
>
;
protected
:
;
;
;
;
public
:
GUI_PLUGIN_NAME(GacUI_Res_ResourceResolver)
vl
::
()
override
{
return
L"GacUI_Res_ResourceResolver"
; }
void
(
vl
::
collections
::
<
>&
)
override
{
}
void
()
override
{
globalStringKeyManager
=
new
();
globalStringKeyManager
->
();
resourceResolverManager
=
this
;
(
new
GuiResourcePathResResolver
::
);
(
new
GuiImportResourcePathResResolver
::
);
}
void
()
override
{
delete
globalStringKeyManager
;
globalStringKeyManager
=
0
;
resourceResolverManager
=
0
;
}
IGuiResourcePathResolverFactory
*
(
const
&
)
override
{
=
.
().
(
);
return
index
==-
1
?
0
:
.
()
index
].
();
}
bool
(
<
IGuiResourcePathResolverFactory
>
)
override
{
if
(
.
().
(
()))
return
false
;
.
(
(),
);
return
true
;
}
*
(
const
&
)
override
{
=
.
().
(
);
return
index
==-
1
?
0
:
.
()
index
].
();
}
bool
(
<
>
)
override
{
if
(
.
().
(
()))
return
false
;
.
(
(),
);
if
(
auto
=
())
{
=
precompile
->
();
for
(
=
0
;
i
<=
maxPassIndex
;
i
++)
{
switch
(
precompile
->
(
i
))
{
case
IGuiResourceTypeResolver_Precompile
::
:
.
(
i
,
());
break
;
case
IGuiResourceTypeResolver_Precompile
::
:
.
(
i
,
());
break
;
default
:;
}
}
}
return
true
;
}
GetMaxPrecompilePassIndex
()
override
{
= -
1
;
FOREACH(Ptr<IGuiResourceTypeResolver>, resolver, typeResolvers.Values())
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
.
());
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
resolver
);)
{
if
(
auto
=
resolver
())
{
=
precompile
->
();
if
(
maxPass
<
pass
)
{
maxPass
=
pass
;
}
}
}
return
maxPass
;
}
GetMaxInitializePassIndex
()
override
{
= -
1
;
FOREACH(Ptr<IGuiResourceTypeResolver>, resolver, typeResolvers.Values())
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
.
());
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
resolver
);)
{
if
(
auto
=
resolver
())
{
=
initialize
->
();
if
(
maxPass
<
pass
)
{
maxPass
=
pass
;
}
}
}
return
maxPass
;
}
void
GetPerResourceResolverNames
(
,
collections
::
<
>&
)
override
{
.
();
=
.
().
(
);
if
(
index
!= -
1
)
{
(
,
.
(
index
));
}
}
void
(
,
collections
::
<
>&
)
override
{
.
();
=
.
().
(
);
if
(
index
!= -
1
)
{
(
,
.
(
index
));
}
}
};
GUI_REGISTER_PLUGIN(GuiResourceResolverManager)
class
GuiRegisterPluginClass_GuiResourceResolverManager
{
public
:
GuiRegisterPluginClass_GuiResourceResolverManager
() {
vl
::
presentation
::
controls
::
()->
(
new
GuiResourceResolverManager
); } }
instance_GuiRegisterPluginClass_GuiResourceResolverManager
;
void
(
const
char
**
,
bool
,
,
,
,
stream
::
&
)
{
if
(
)
{
;
(
,
false
,
,
,
,
compressedStream
);
compressedStream
.
(
0
);
(
compressedStream
,
);
}
else
{
for
(
=
0
;
i
<
;
i
++)
{
=
i
==
-
1
?
:
;
.
((
void
*)
[
i
],
size
);
}
}
}
}
}