YSTest: Initialization.cpp 源文件

YSTest PreAlpha_b900_20201012 The YSLib Test Project

Initialization.cpp
浏览该文件的文档.
1 /*
2 © 2009-2020 FrankHB.
3
4 This file is part of the YSLib project, and may only be used,
5 modified, and distributed under the terms of the YSLib project
6 license, LICENSE.TXT. By continuing to use, modify, or distribute
7 this file you indicate that you have read the license and
8 understand and accept it fully.
9 */
10
28 #include "Helper/YModules.h"
29 #include YFM_Helper_Initialization // for IO::Path, IO::FetchSeparator,
30 // IO::MaxPathLength, FetchCurrentWorkingDirectory, ystdex::nptr, pair, map,
31 // mutex, lock_guard, IO::EnsureDirectory, IO::VerifyDirectory,
32 // PerformKeyAction, IO::TraverseChildren, NativePathView;
33 #if !(YCL_Win32 || YCL_Linux)
34 # include <ystdex/string.hpp> // for ystdex::rtrim;
35 # include YFM_YCLib_FileSystem // for platform::EndsWithNonSeperator;
36 #endif
37 #include <ystdex/range.hpp> // for ystdex::begin, ystdex::end;
38 #include <ystdex/algorithm.hpp> // for ystdex::fast_all_of;
39 #if YCL_Win32
40 # include YFM_Win32_YCLib_NLS // for platform_ex::FetchDBCSOffset,
41 // platform_ex::WCSToUTF8, platform_ex::UTF8ToWCS;
42 #endif
43 #include YFM_CHRLib_MappingEx // for CHRLib::cp113_lkp;
44 #include YFM_NPL_Configuration // for NPL::Configuration, NPL::Session,
45 // A1::LoadNode;
46 #include YFM_YSLib_Service_TextFile // for Text::BOM_UTF_8, Text::CheckBOM;
47 #include <ystdex/string.hpp> // for ystdex::write_literal, ystdex::sfmt;
48 #include <cerrno> // for errno;
49 #include <ystdex/scope_guard.hpp> // for ystdex::swap_guard;
50 #include YFM_YSLib_Core_YCoreUtilities // for FetchEnvironmentVariable;
51 #include YFM_Helper_GUIApplication // for FetchAppInstance,
52 // Application::AddExit, FetchEnvironment;
53 #include YFM_YSLib_Core_YException // for ExtractAndTrace;
54 #include YFM_YSLib_Core_YStorage // for FetchStaticRef;
55 #include YFM_Helper_Environment // for complete type Environment introduced by
56 // FetchEnvironment;
57
58 using namespace platform;
60 using namespace NPL;
61
62 namespace YSLib
63 {
64
65 using namespace Drawing;
66 using namespace IO;
67
68 #if YCL_DS
69 bool ShowInitializedLog(true);
70 #endif
71
72 namespace
73 {
74
76 unique_ptr<ValueNode> p_root;
78 yconstexpr const char TU_MIME[]{R"NPLA1(
79 (application
80 (octet-stream "bin" "so")
81 (x-msdownload "exe" "dll" "com" "bat" "msi")
82 (x-font-ttf "ttf" "ttc")
83 (xml "xml")
84 (zip "zip")
85 )
86 (audio
87 (midi "mid" "midi" "rmi")
88 (mpeg "mp3")
89 (x-mpegurl "m3u")
90 (x-wav "wav")
91 )
92 (image
93 (bmp "bmp")
94 (gif "gif")
95 (jpeg "jpeg" "jpg")
96 (png "png")
97 (tif "tif" "tiff")
98 )
99 (text
100 (html "html" "htm")
101 (plain "txt" "conf" "def" "ini" "log" "in")
102 (x-c "c" "h" "inl")
103 (x-c++ "cc" "cpp" "cxx" "h" "hh" "hpp" "hxx" "inl")
104 )
105 )NPLA1"};
106
108
109 #if YCL_Win32 || (YCL_Linux && !YCL_Android)
110 # define YF_Helper_Initialization_UseFallbackConf_ true
111 #endif
112
113 struct RootPathCache
114 {
115 string PathString;
116 IO::Path Path;
117 IO::Path Parent;
118
119 // XXX: Similar to %FetchConfPaths as of the concurrent execution.
120 RootPathCache()
121 : PathString([]{
122 #if YCL_Win32
123 IO::Path image(platform::ucast(
124 platform_ex::FetchModuleFileName().data()));
125
126 if(!image.empty())
127 {
128 image.pop_back();
129
130 const auto& dir(image.Verify());
131
132 if(!dir.empty() && dir.back() == FetchSeparator<char16_t>())
133 return dir.GetMBCS();
134 }
135 #elif YCL_Android
136 const char*
137 sd_paths[]{"/sdcard/", "/mnt/sdcard/", "/storage/sdcard0/"};
138
139 for(const auto& path : sd_paths)
140 if(IO::VerifyDirectory(path))
141 {
142 YTraceDe(Informative, "Successfully found SD card path"
143 " '%s' as root path.", path);
144 return path;
145 }
146 else
147 YTraceDe(Informative,
148 "Failed accessing SD card path '%s'.", path);
149 #elif YCL_Linux
150 // FIXME: What if link reading failed (i.e. permission denied)?
151 // XXX: Link content like 'node_type:[inode]' is not supported.
152 auto image(IO::ResolvePath<ystdex::path<vector<string>,
153 IO::PathTraits>>(string_view("/proc/self/exe")));
154
155 if(!image.empty())
156 {
157 image.pop_back();
158
159 const auto& dir(IO::VerifyDirectoryPathTail(
160 ystdex::to_string_d(image)));
161
162 if(!dir.empty() && dir.back() == FetchSeparator<char>())
163 return dir;
164 }
165 #else
166 // XXX: Trimming is necessary, because it is unspecified to have
167 // trailing slashes with %platform::ugetcwd as POSIX.1 2004.
168 auto root_path(ystdex::rtrim(FetchCurrentWorkingDirectory<char>(
169 IO::MaxPathLength), IO::FetchSeparator<char>()));
170
171 YAssert(platform::EndsWithNonSeperator(root_path),
172 "Invalid argument found.");
173 root_path += IO::FetchSeparator<char>();
174 return root_path;
175 // TODO: Add similar implemnetation for BSD family OS, etc.
176 #endif
177 throw GeneralEvent("Failed finding working root path.");
178 }()), Path(PathString), Parent(Path / u"..")
179 {
180 YTraceDe(Informative, "Initialized root directory path '%s'.",
181 PathString.c_str());
182 }
183 };
184
185 YB_ATTR_nodiscard YB_PURE const RootPathCache&
186 FetchRootPathCache()
187 {
188 static const RootPathCache cache;
189
190 return cache;
191 }
192
193 #if YF_Helper_Initialization_UseFallbackConf_
194 // XXX: Currently all platforms using fallback configurations have the same
195 // image path and root path.
196 YB_ATTR_nodiscard YB_PURE inline const RootPathCache&
197 FetchImagePathCache()
198 {
199 return FetchRootPathCache();
200 }
201 #endif
202
203 template<class _tRange>
204 YB_ATTR_nodiscard YB_PURE bool
205 CheckLocalFHSLayoutOn(const _tRange& c)
206 {
207 return ystdex::fast_all_of(ystdex::begin(c), ystdex::end(c),
208 [](const IO::Path& pth) ynothrow -> bool{
209 TryRet(IO::VerifyDirectory(pth))
210 CatchRet(..., {})
211 });
212 }
213
214 YB_ATTR_nodiscard YB_PURE bool
215 CheckLocalFHSLayoutImpl(const IO::Path& prefix, IO::Path bin)
216 {
217 if(bin != prefix)
218 {
219 const IO::Path
220 paths[]{prefix, std::move(bin), prefix / u"lib", prefix / u"share"};
221
222 return CheckLocalFHSLayoutOn(paths);
223 }
224 return {};
225 }
226
227 YB_ATTR_nodiscard YB_PURE bool
228 CheckLocalFHSLayoutWithCache(const RootPathCache& cache)
229 {
230 # if true
231 // XXX: This is more efficient.
232 return CheckLocalFHSLayoutImpl(cache.Parent, cache.Path);
233 # else
234 return CheckLocalFHSLayout(cache.PathString);
235 # endif
236 }
237
238 YB_ATTR_nodiscard YB_PURE const string&
239 FetchPreferredConfPath()
240 {
241 #if YF_Helper_Initialization_UseFallbackConf_
242 static string conf_path([]() -> string{
243 auto& cache(FetchImagePathCache());
244
245 if(CheckLocalFHSLayoutWithCache(cache))
246 {
247 YTraceDe(Informative, "FHS layout is detected, using"
248 " '../var/YSLib/' relative to the program image path as the"
249 " preferred configuration path.");
250 return (cache.Parent / u"var" / u"YSLib").GetString().GetMBCS();
251 }
252 YTraceDe(Informative, "FHS layout is not detected, using the root path"
253 " as the preferred configuration path.");
254 return FetchRootPathString();
255 }());
256
257 return conf_path;
258 #else
259 return FetchRootPathString();
260 #endif
261 }
263
264 #if YCL_DS
265 # define YF_Helper_Initialization_DataDirectory_ "/Data/"
266 # define YF_Helper_Initialization_FontDirectory_ "/Font/"
267 # define YF_Helper_Initialization_FontFile_ "/Font/FZYTK.TTF"
268 #elif YCL_Win32
269 # define YF_Helper_Initialization_DataDirectory_ FetchRootPathString()
270 # define YF_Helper_Initialization_FontFile_ \
271 (FetchSystemFontDirectory_Win32() + "SimSun.ttc")
272 inline PDefH(string, FetchSystemFontDirectory_Win32, )
274 // NOTE: Hard-coded as Shell32 special path with %CSIDL_FONTS or
275 // %CSIDL_FONTS. See https://msdn.microsoft.com/en-us/library/dd378457.aspx.
276 ImplRet(platform_ex::WCSToUTF8(platform_ex::FetchWindowsPath()) + "Fonts\\")
277 #elif YCL_Android
278 # define YF_Helper_Initialization_DataDirectory_ (FetchRootPathString() + "Data/")
279 # define YF_Helper_Initialization_FontDirectory_ "/system/fonts/"
280 # define YF_Helper_Initialization_FontFile_ \
281 "/system/fonts/DroidSansFallback.ttf"
282 #elif YCL_Linux
283 # define YF_Helper_Initialization_DataDirectory_ FetchRootPathString()
284 # define YF_Helper_Initialization_FontFile_ "./SimSun.ttc"
285 #else
286 # error "Unsupported platform found."
287 #endif
288 #ifndef YF_Helper_Initialization_DataDirectory_
289 # error "Data directory shall be defined."
290 #endif
291 #ifndef YF_Helper_Initialization_FontDirectory_
292 # define YF_Helper_Initialization_FontDirectory_ \
293 YF_Helper_Initialization_DataDirectory_
294 #endif
295
296 #if !CHRLib_NoDynamic_Mapping
297 MappedFile
299 LoadMappedModule(const std::string& path)
300 {
301 TryRet(MappedFile(path))
302 CatchExpr(..., std::throw_with_nested(
303 GeneralEvent("Loading module '" + path + "' failed.")))
304 YAssert(false, "Unreachable control found.");
305 }
306
307 # if YCL_Win32
308 const unsigned short* p_dbcs_off_936;
310 # endif
311
313 class CMap final
314 {
315 private:
316 MappedFile mapped{};
317 # if YCL_Win32
318 nptr<char16_t(*)(byte, byte)> cp113_lkp_backup = {};
319 # endif
320
321 public:
322 CMap(const string& data_dir)
323 {
324 const std::string mapping_name(to_std_string(data_dir) + "cp113.bin");
325
326 YTraceDe(Notice, "Loading character mapping file '%s' ...",
327 mapping_name.c_str());
328 try
329 {
330 mapped = LoadMappedModule(mapping_name);
331 if(mapped.GetSize() != 0)
332 CHRLib::cp113 = mapped.GetPtr();
333 else
334 throw GeneralEvent("Failed loading CHRMapEx.");
335 YTraceDe(Notice, "CHRMapEx loaded successfully.");
336 }
337 catch(std::exception& e)
338 {
339 YTraceDe(Notice, "Module cp113.bin loading failed, error: %s",
340 e.what());
341 # if YCL_Win32
342 if((p_dbcs_off_936 = platform_ex::FetchDBCSOffset(936)))
343 {
344 cp113_lkp_backup = CHRLib::cp113_lkp;
345 CHRLib::cp113_lkp = [](byte seq0, byte seq1) ynothrowv
346 -> char16_t{
347 return p_dbcs_off_936[size_t(p_dbcs_off_936[size_t(seq0)])
348 + size_t(seq1)];
349 };
350 }
351 if(p_dbcs_off_936)
352 YTraceDe(Notice, "NLS CP936 used as fallback.");
353 else
354 # endif
355 {
356 CHRLib::cp113_lkp
357 = [](byte, byte) YB_ATTR_LAMBDA(noreturn) -> char16_t{
358 throw
359 LoggedEvent("Failed calling conversion for CHRMapEx.");
360 };
361 YTraceDe(Warning, "CHRMapEx conversion calls would lead to"
362 " exception thrown.");
363 }
364 }
365 }
366 ~CMap()
367 {
368 # if YCL_Win32
369 if(cp113_lkp_backup)
370 CHRLib::cp113_lkp = cp113_lkp_backup.get();
371 # endif
372 if(mapped)
373 {
374 mapped = MappedFile();
375 YTraceDe(Notice, "Character mapping deleted.");
376 }
377 }
378
379 DefDeMoveCtor(CMap)
380 };
381 #endif
382
384 inline void
385 WriteNPLA1Stream(std::ostream& os, NPL::Configuration&& conf)
386 {
387 ystdex::write_literal(os, Text::BOM_UTF_8) << std::move(conf);
388 }
389
391 YB_ATTR_nodiscard ValueNode
392 TryReadRawNPLStream(std::istream& is)
393 {
394 NPL::Configuration conf;
395
396 is >> conf;
397 YTraceDe(Debug, "Plain configuration loaded.");
398 if(!conf.GetNodeRRef().empty())
399 return conf.GetNodeRRef();
400 YTraceDe(Warning, "Empty configuration found.");
401 throw GeneralEvent("Invalid stream found when reading configuration.");
402 }
403
405
406 YB_ATTR_nodiscard YB_NONNULL(1, 2) ValueNode
407 LoadNPLA1FileDirect(const char* disp, const char* path, bool show_info)
408 {
409 if(show_info)
410 YTraceDe(Notice, "Found %s '%s'.", Nonnull(disp), path);
411 // XXX: Race condition may cause failure, though file would not be
412 // corrupted now.
413 if(SharedInputMappedFileStream sifs{path})
414 {
415 YTraceDe(Debug, "Accessible configuration file found.");
416 if(Text::CheckBOM(sifs, Text::BOM_UTF_8))
417 return TryReadRawNPLStream(sifs);
418 YTraceDe(Warning, "Wrong encoding of configuration file found.");
419 }
420 YTraceDe(Err, "Configuration corrupted.");
421 return {};
422 }
423
424 YB_ATTR_nodiscard YB_NONNULL(1, 2, 3) ValueNode
425 LoadNPLA1FileCreate(const char* disp, const char* path,
426 ValueNode(*creator)(), bool show_info)
427 {
428 if(show_info)
429 YTraceDe(Notice, "Creating %s '%s'...", disp, path);
430
431 ystdex::swap_guard<int, void, decltype(errno)&> gd(errno, 0);
432
433 // XXX: Failed on race condition detected.
434 if(UniqueLockedOutputFileStream uofs{path, std::ios_base::out
435 | std::ios_base::trunc | platform::ios_noreplace})
436 WriteNPLA1Stream(uofs, Nonnull(creator)());
437 else
438 {
439 int err(errno);
440
441 YTraceDe(Warning, "Cannot create file, possible error"
442 " (from errno) = %d: %s.", err, std::strerror(err));
443 YTraceDe(Warning,"Creating default file failed.");
444 return {};
445 }
446 YTraceDe(Debug, "Created configuration.");
447 return LoadNPLA1FileDirect(disp, path, show_info);
448 }
449
450 YB_ATTR_nodiscard YB_NONNULL(1) ValueNode
451 LoadNPLA1MemoryFallback(ValueNode(*creator)())
452 {
453 YTraceDe(Notice, "Trying fallback in memory...");
454
455 std::stringstream ss;
456
457 ss << Nonnull(creator)();
458 return TryReadRawNPLStream(ss);
459 }
460
461 yconstexpr const char* ConfFileDisp("configuration file");
462
463 #if YF_Helper_Initialization_UseFallbackConf_
464 using ValueNodeLoadEntry = pair<string, ValueNode(*)()>;
465 using VecRecordMap = map<string, string>;
466
467 mutex NPLA1PathVecRecordMutex;
468
469 YB_ATTR_nodiscard YB_PURE VecRecordMap&
470 FetchNPLA1PathVecRecordRef()
471 {
472 static VecRecordMap m;
473
474 return m;
475 }
476
477 inline YB_NONNULL(1) void
478 AddNPLA1FileVecRecordItem(const char* disp, const string& conf_path)
479 {
480 FetchNPLA1PathVecRecordRef().emplace(disp, conf_path);
481 }
482
483 YB_ATTR_nodiscard YB_NONNULL(1, 3, 4) ValueNode
484 LoadNPLA1FileVec(const char* disp, const vector<string>& conf_paths,
485 const char* filename, ValueNode(*creator)(), bool show_info)
486 {
487 auto res(TryInvoke([=]() -> ValueNode{
488 for(const auto& conf_path : conf_paths)
489 {
490 const auto e(conf_path + filename);
491 const auto path(e.c_str());
492
493 if(ufexists(path))
494 {
495 const lock_guard<mutex> gd(NPLA1PathVecRecordMutex);
496 auto r(LoadNPLA1FileDirect(disp, path, show_info));
497
498 if(r)
499 AddNPLA1FileVecRecordItem(disp, conf_path);
500 return r;
501 }
502 YTraceDe(Debug, "Path '%s' access failed.", path);
503 }
504 for(const auto& conf_path : conf_paths)
505 {
506 TryExpr(IO::EnsureDirectory(conf_path))
507 catch(std::system_error&)
508 {
509 continue;
510 }
511
512 const auto e(conf_path + filename);
513 const lock_guard<mutex> gd(NPLA1PathVecRecordMutex);
514 auto conf(LoadNPLA1FileCreate(disp, e.c_str(), creator, show_info));
515
516 if(conf)
517 {
518 AddNPLA1FileVecRecordItem(disp, conf_path);
519 return conf;
520 }
521 }
522 return {};
523 }));
524
525 return res ? res : LoadNPLA1MemoryFallback(creator);
526 }
527
528 const vector<string>&
529 FetchConfPaths()
530 {
531 static const struct Init
532 {
533 vector<string> Paths;
534
535 // XXX: This may be concurrently executed across multiple threads
536 // without %call_once. This is still assumed safe (free of race)
537 // because the result shall be the same in each thread.
538 Init()
539 : Paths([]() -> vector<string>{
540 vector<string> res{FetchPreferredConfPath()};
541 string var;
542
543 if(FetchEnvironmentVariable(var, "HOME") && !var.empty())
544 {
545 AddPostfix(var);
546 res.push_back(std::move(var));
547 var.clear();
548 }
549 #if YCL_Win32
550 if(FetchEnvironmentVariable(var, "USERPROFILE") && !var.empty())
551 {
552 AddPostfix(var);
553 res.push_back(std::move(var));
554 var.clear();
555 }
556 #endif
557 return res;
558 }())
559 {
560 YTraceDe(Informative,
561 "Initialized enumerated configuration root paths.");
562 }
563
564 private:
565 static inline void
566 AddPostfix(string& var)
567 {
568 var += FetchSeparator<char>();
569 var += ".YSLib";
570 var += FetchSeparator<char>();
571 }
572 } init;
573
574 return init.Paths;
575 }
576 #endif
577
578 YB_ATTR_nodiscard YB_PURE const string&
579 FetchConfPathForSave()
580 {
581 #if YF_Helper_Initialization_UseFallbackConf_
582 const auto& vr(FetchNPLA1PathVecRecordRef());
583 const lock_guard<mutex> gd(NPLA1PathVecRecordMutex);
584 const auto i(vr.find(ConfFileDisp));
585
586 return i != vr.end() ? i->second : FetchPreferredConfPath();
587 #else
588 return FetchPreferredConfPath();
589 #endif
590 }
592
594 template<typename _type, typename _fLoader, typename _func>
595 _type&
596 FetchDefaultResource(_fLoader load, _func f)
597 {
598 static mutex mtx;
599 static observer_ptr<_type> p_res;
600 lock_guard<mutex> lck(mtx);
601
602 if(YB_UNLIKELY(!p_res))
603 {
604 // TODO: Simplify?
605 const auto p_locked(FetchAppInstance().LockAddExit(load()));
606
607 p_res = make_observer(&f(FetchRoot()["YFramework"], *p_locked));
608 }
609 #if YCL_DS
610 // XXX: Actually this should be set after %InitVideo call.
611 ShowInitializedLog = {};
612 #endif
613 return *p_res;
614 }
615
616 } // unnamed namespace;
617
618 void
619 TraceForOutermost(const std::exception& e, RecordLevel lv) ynothrow
620 {
621 #if YCL_DS
622 ShowInitializedLog = {};
623 #endif
624 if(const auto p = dynamic_cast<const YSLib::FatalError*>(&e))
625 {
626 #if YCL_Win32
627 using platform_ex::UTF8ToWCS;
628
629 FilterExceptions([&]{
630 ::MessageBoxW({}, UTF8ToWCS(p->GetContent()).c_str(),
631 UTF8ToWCS(p->GetTitle()).data(), MB_ICONERROR);
632 });
633 #endif
634 YTraceDe(Emergent, "%s\n\n%s", p->GetTitle(), p->GetContent().data());
635 terminate();
636 }
637 else
638 ExtractAndTrace(e, lv);
639 }
640
641
642 bool
643 CheckLocalFHSLayout(const string& path_string)
644 {
645 IO::Path bin(path_string);
646 const auto prefix(bin / u"..");
647
648 return CheckLocalFHSLayoutImpl(prefix, std::move(bin));
649 }
650
651 const IO::Path&
652 FetchLocalFHSRootPath()
653 {
654 #if true
655 // XXX: This is more efficient.
656 auto& cache(FetchRootPathCache());
657
658 if(CheckLocalFHSLayoutWithCache(cache))
659 return cache.Parent;
660 return FetchStaticRef<const IO::Path>();
661 #else
662 static const auto path(GetLocalFHSRootPathOf(FetchRootPathString()));
663
664 return path;
665 #endif
666 }
667
668 const string&
669 FetchRootPathString()
670 {
671 return FetchRootPathCache().PathString;
672 }
673
674 IO::Path
675 GetLocalFHSRootPathOf(const string& path_string)
676 {
677 #if true
678 // XXX: This is more efficient.
679 IO::Path bin(path_string);
680 auto prefix(bin / u"..");
681
682 if(CheckLocalFHSLayoutImpl(prefix, std::move(bin)))
683 return prefix;
684 #else
685 if(CheckLocalFHSLayout(path_string))
686 return IO::Path(path_string) / u"..";
687 #endif
688 return {};
689 }
690
691
692 ValueNode
693 LoadNPLA1File(const char* disp, const char* path, ValueNode(*creator)(),
694 bool show_info)
695 {
696 auto res(TryInvoke([=]() -> ValueNode{
697 if(ufexists(path))
698 return LoadNPLA1FileDirect(disp, path, show_info);
699 YTraceDe(Debug, "Path '%s' access failed.", path);
700 return LoadNPLA1FileCreate(disp, path, creator, show_info);
701 }));
702
703 return res ? std::move(res) : LoadNPLA1MemoryFallback(creator);
704 }
705
706 void
707 LoadComponents(Application& app, const ValueNode& node)
708 {
709 const auto& data_dir(AccessChild<string>(node, "DataDirectory"));
710 const auto& font_path(AccessChild<string>(node, "FontFile"));
711 const auto& font_dir(AccessChild<string>(node, "FontDirectory"));
712
713 if(!data_dir.empty() && !font_path.empty() && !font_dir.empty())
714 YTraceDe(Notice, "Loaded default directory:\n%s\nLoaded default"
715 " font path:\n%s\nLoaded default font directory:\n%s",
716 data_dir.c_str(), font_path.c_str(), font_dir.c_str());
717 else
718 throw GeneralEvent("Empty path loaded.");
719 #if !CHRLib_NoDynamicMapping
720 app.AddExit(CMap(data_dir));
721 #endif
722 YTraceDe(Notice, "Trying entering directory '%s' ...", data_dir.c_str());
723 if(!IO::VerifyDirectory(data_dir))
724 throw GeneralEvent("Invalid default data directory found.");
725 if(!(ufexists(font_path.c_str()) || IO::VerifyDirectory(font_dir)))
726 throw GeneralEvent("Invalid default font file path found.");
727 }
728
729 ValueNode
730 LoadConfiguration(bool show_info)
731 {
732 ValueNode(*creator)()([]{
733 return ValueNode(NodeLiteral{"YFramework",
734 {{"DataDirectory", YF_Helper_Initialization_DataDirectory_},
735 {"FontFile", YF_Helper_Initialization_FontFile_},
736 {"FontDirectory", YF_Helper_Initialization_FontDirectory_}}});
737 });
738
739 #if YF_Helper_Initialization_UseFallbackConf_
740 return LoadNPLA1FileVec(ConfFileDisp, FetchConfPaths(), "yconf.txt",
741 creator, show_info);
742 #else
743 return LoadNPLA1File(ConfFileDisp,
744 (FetchPreferredConfPath() + "yconf.txt").c_str(), creator, show_info);
745 #endif
746 #undef YF_Helper_Initialization_UseFallbackConf_
747 }
748
749 void
750 SaveConfiguration(const ValueNode& node)
751 {
752 if(UniqueLockedOutputFileStream uofs{
753 (FetchConfPathForSave() + "yconf.txt").c_str(),
754 std::ios_base::out | std::ios_base::trunc})
755 {
756 YTraceDe(Debug, "Writing configuration...");
757 WriteNPLA1Stream(uofs, ValueNode(node.GetContainer()));
758 }
759 else
760 throw GeneralEvent("Invalid file found when writing configuration.");
761 YTraceDe(Debug, "Writing configuration done.");
762 }
763
764 #undef YF_Helper_Initialization_DataDirectory_
765 #undef YF_Helper_Initialization_FontDirectory_
766 #undef YF_Helper_Initialization_FontFile_
767
768
769 void
770 InitializeSystemFontCache(FontCache& fc, const string& font_file,
771 const string& font_dir)
772 {
773 string res;
774
775 YTraceDe(Notice, "Loading font files...");
776 PerformKeyAction([&]{
777 size_t loaded(fc.LoadTypefaces(font_file) != 0 ? 1 : 0);
778
779 if(!font_dir.empty())
780 try
781 {
782 IO::TraverseChildren(font_dir,
783 [&](NodeCategory c, NativePathView npv){
784 if(!bool(c & NodeCategory::Directory))
785 {
786 const FontPath path(font_dir + String(npv).GetMBCS());
787
788 if(path != font_file && fc.LoadTypefaces(path) != 0)
789 ++loaded;
790 }
791 });
792 }
793 CatchExpr(std::system_error& e, YTraceDe(Warning,
794 "Failed loading font directory."), ExtractAndTrace(e, Warning))
795 fc.InitializeDefaultTypeface();
796
797 const auto faces(fc.GetFaces().size());
798
799 if(faces != 0)
800 YTraceDe(Notice, "%zu face(s) in %zu font file(s)"
801 " are loaded\nsuccessfully.\n", faces, loaded);
802 else
803 throw GeneralEvent("No fonts found.");
804 YTraceDe(Notice, "Setting default font face...");
805 if(const auto pf = fc.GetDefaultTypefacePtr())
806 YTraceDe(Notice, "\"%s\":\"%s\",\nsuccessfully.",
807 pf->GetFamilyName().c_str(), pf->GetStyleName().c_str());
808 else
809 throw GeneralEvent("Setting default font face failed.");
810 }, yfsig, " Font Caching Failure ",
811 " Please make sure the fonts are\n stored in correct path.\n");
812 }
813
814
815 ValueNode&
816 FetchRoot() ynothrow
817 {
818 return FetchEnvironment().Root;
819 }
820
821 Drawing::FontCache&
822 FetchDefaultFontCache()
823 {
824 return FetchDefaultResource<Drawing::FontCache>([]{
825 return make_unique<Drawing::FontCache>();
826 }, [](ValueNode& node, unique_ptr<Drawing::FontCache>& locked)
827 -> Drawing::FontCache&{
828 InitializeSystemFontCache(*locked,
829 AccessChild<string>(node, "FontFile"),
830 AccessChild<string>(node, "FontDirectory"));
831 return *locked.get();
832 });
833 }
834
835 MIMEBiMapping&
836 FetchMIMEBiMapping()
837 {
838 return FetchDefaultResource<MIMEBiMapping>([]{
839 return MIMEBiMapping();
840 }, [](ValueNode& node, MIMEBiMapping& locked) -> MIMEBiMapping&{
841 AddMIMEItems(locked, LoadNPLA1File("MIME database", (AccessChild<string>
842 (node, "DataDirectory") + "MIMEExtMap.txt").c_str(), []{
843 NPL::Session sess{};
844
845 return A1::LoadNode(
846 SContext::Analyze(sess, sess.Process(TU_MIME)));
847 }, true));
848 return locked;
849 });
850 }
851
852 } // namespace YSLib;
853
YSLib::IO::Path
路径。
Definition: YSLib/Service/FileSystem.h:217
YSLib::FetchMIMEBiMapping
YF_API MIMEBiMapping & FetchMIMEBiMapping()
取 MIME 类型名和文件扩展名双向映射对象。
Definition: Initialization.cpp:836
YB_ATTR_nodiscard
#define YB_ATTR_nodiscard
标记返回值不被忽略的属性。
Definition: ydef.h:715
CHRLib::e
const char const char * e
Definition: CharacterProcessing.h:112
Path
IO::Path Path
Definition: Initialization.cpp:116
YSLib::CheckLocalFHSLayout
bool CheckLocalFHSLayout(const string &path_string)
Definition: Initialization.cpp:643
YSLib::InitializeSystemFontCache
void InitializeSystemFontCache(FontCache &fc, const string &font_file, const string &font_dir)
Definition: Initialization.cpp:770
string.hpp
ISO C++ 标准字符串扩展。
platform::Nonnull
YB_PURE _type && Nonnull(_type &&p) ynothrowv
断言并返回非空参数。
Definition: Debug.h:518
YSLib::TryInvoke
ystdex::nonvoid_result_t< ystdex::invoke_result_t< _fCallable, _tParams... > > TryInvoke(_fCallable &&f, _tParams &&... args) ynothrow
调用函数并尝试返回。
Definition: YException.h:206
CHRLib::c
c
Definition: CharacterProcessing.h:84
yconstexpr
#define yconstexpr
指定编译时常量表达式。
Definition: ydef.h:1072
YB_PURE
#define YB_PURE
指示函数或函数模板实例为纯函数。
Definition: ydef.h:919
YSLib::GetLocalFHSRootPathOf
IO::Path GetLocalFHSRootPathOf(const string &path_string)
Definition: Initialization.cpp:675
ystdex::cpp2017::basic_string
Definition: string.hpp:77
platform_ex
平台扩展命名空间。
Definition: Android.h:46
platform::Descriptions::Emergent
@ Emergent
Definition: YCommon.h:179
YSLib::Drawing::r
The boundary is out of the const Graphics const Rect const Point const Point Color c const Rect const Rect & r
Definition: YDraw.h:174
ystdex::cpp2017::basic_string_view
Definition: string_view.hpp:95
CHRLib::cp113_lkp
char16_t(* cp113_lkp)(byte, byte)
查找编码转换序列的实现。
Definition: MappingEx.cpp:64
YSLib::Application::AddExit
void AddExit(_tParam &&arg)
Definition: YApplication.h:109
YSLib::FetchAppInstance
YF_API Application & FetchAppInstance()
取应用程序实例。
Definition: GUIApplication.cpp:295
ystdex::nptr
可空指针包装：满足 NullablePointer 要求同时满足转移后为空。
Definition: pointer.hpp:122
yfsig
#define yfsig
展开为表示函数签名的预定义变量的宏。
Definition: ydef.h:1133
platform::Descriptions::RecordLevel
RecordLevel
记录等级。
Definition: YCommon.h:178
ystdex::cpp2017::string_view
basic_string_view< char > string_view
Definition: string_view.hpp:437
DefDeMoveCtor
#define DefDeMoveCtor(_t)
Definition: YBaseMacro.h:167
YSLib::Text::CheckBOM
YB_ATTR_nodiscard YB_PURE CheckBOM
Definition: TextFile.h:83
platform::path
_tString && path
Definition: YCLib/FileSystem.h:464
platform::size_t
YB_ATTR_nodiscard YF_API size_t
Definition: FileIO.h:1345
YSLib::IO::int
YF_API int
Definition: File.h:51
YSLib::AddMIMEItems
YF_API void AddMIMEItems(MIMEBiMapping &, const ValueNode &, MIMEBiMapping::MIMEType &&={})
根据 NPLA1 节点内容增加 MIME 映射。
Definition: ContentType.cpp:62
Parent
IO::Path Parent
Definition: Initialization.cpp:117
YSLib::UI::fc
fc
Definition: Console.h:93
ystdex::path
一般路径模板。
Definition: path.hpp:268
YSLib::PerformKeyAction
YF_API void PerformKeyAction(function< void()>, const char *, const char *, string_view)
执行关键动作。
Definition: YCoreUtilities.cpp:38
YSLib::FetchDefaultFontCache
YF_API Drawing::FontCache & FetchDefaultFontCache()
取默认字体缓存。
Definition: Initialization.cpp:822
YSLib::GeneralEvent
std::runtime_error GeneralEvent
一般运行时异常事件类。
Definition: YException.h:46
platform::MappedFile
只读内存映射文件。
Definition: MemoryMapping.h:115
YModules.h
Helper 库模块配置文件。
platform_ex::Windows::WCSToUTF8
const char *str string_view sv WCSToUTF8
Definition: NLS.h:79
YSLib::Drawing::FontCache
字体缓存。
Definition: Font.h:467
platform::strings::to_std_string
_tString to_std_string(basic_string_view< _tChar > sv)
Definition: Container.h:256
CHRLib::f
f(d, s)
YAssert
#define YAssert(_expr, _msg)
Definition: cassert.h:154
ystdex::map
映射容器。
Definition: map.hpp:79
ystdex::write_literal
std::basic_ostream< _tChar, _tTraits > & write_literal(std::basic_ostream< _tChar, _tTraits > &os, const _tChar(&s)[_vN])
Definition: string.hpp:1785
platform::terminate
YB_NORETURN YF_API void terminate() ynothrow
终止函数。
Definition: YCommon.cpp:48
YSLib::show_info
YB_ATTR_nodiscard YF_API const char ValueNode(*) boo show_info)
Definition: Initialization.h:117
YSLib::lv
const char RecordLevel lv
Definition: YException.cpp:61
YSLib::SaveConfiguration
YF_API void SaveConfiguration(const ValueNode &)
保存默认配置。
Definition: Initialization.cpp:750
ystdex::state_guard
使用临时状态暂存对象的作用域守卫。
Definition: scope_guard.hpp:273
YSLib::FetchEnvironmentVariable
bool FetchEnvironmentVariable(string &res, const char *var)
Definition: YCoreUtilities.cpp:77
YSLib::Application
程序实例。
Definition: YApplication.h:47
platform_ex::Windows::UTF8ToWCS
UTF8ToWCS
Definition: NLS.h:72
CHRLib::cp113
byte * cp113
Definition: MappingEx.cpp:57
platform::ImplRet
YB_ATTR_nodiscard const char *s ImplRet(Nonnull(s)) YB_ATTR_nodiscard inline PDefH(const string &
YSLib::LoggedEvent
记录日志的异常事件类。
Definition: YException.h:51
ystdex::make_observer
observer_ptr< _type > make_observer(_type *p)
Definition: pointer.hpp:405
YSLib::TraceForOutermost
YF_API void TraceForOutermost(const std::exception &, RecordLevel) ynothrow
处理最外层边界的异常，若捕获致命错误则在之后终止程序。
Definition: Initialization.cpp:619
YSLib::IO::EnsureDirectory
EnsureDirectory
Definition: YSLib/Service/FileSystem.h:558
platform::ynothrow
const _tString &path ynothrow
Definition: YCLib/FileSystem.h:453
ystdex::cpp2017::data
auto data(_tRange &c) -> decltype(c.data())
Definition: range.hpp:581
NPL::Configuration
设置：使用 S 表达式存储外部状态。
Definition: NPL/Configuration.h:65
YSLib::Text::String
YSLib 标准字符串（使用 UCS-2 作为内部编码）。
Definition: YString.h:47
scope_guard.hpp
作用域守卫。
platform::Descriptions::Notice
@ Notice
Definition: YCommon.h:184
ystdex::cpp2017::end
auto end(_tRange &c) -> decltype(c.end())
Definition: range.hpp:345
platform::Descriptions::Informative
@ Informative
Definition: YCommon.h:185
ystdex::rtrim
_tString && rtrim(_tString &&str, typename string_traits< _tString >::value_type c)
删除字符串中指定的连续后缀字符。
Definition: string.hpp:1454
YSLib::ValueNode
值类型节点。
Definition: ValueNode.h:73
YSLib::ExtractAndTrace
YF_API void ExtractAndTrace(const std::exception &, RecordLevel=Err) ynothrow
使用 TraceException 展开和跟踪异常类型和信息。
platform_ex::Windows::FetchModuleFileName
YF_API wstring FetchModuleFileName(::HMODULE={}, YSLib::RecordLevel=YSLib::Err)
取模块映像路径。
YSLib::i
return i
Definition: YCoreUtilities.h:177
platform::ios::stringstream
stringstream_for< string > stringstream
Definition: Container.h:330
YTraceDe
#define YTraceDe(...)
YCLib 默认调试跟踪。
Definition: Debug.h:407
YSLib::FilterExceptions
bool FilterExceptions(_func f, const char *desc={}, RecordLevel lv=Alert, ExceptionTracer trace=ExtractAndTrace) ynothrow
调用函数并过滤宿主异常。
Definition: YException.h:225
YSLib::MIMEBiMapping
MIME 和文件扩展名双向映射。
Definition: ContentType.h:45
YSLib::FetchRoot
YF_API ValueNode & FetchRoot() ynothrow
取值类型根节点。
Definition: Initialization.cpp:816
platform::Descriptions::Err
@ Err
Definition: YCommon.h:182
platform_ex::Windows::Directory
@ Directory
Definition: Win32/include/YCLib/MinGW32.h:466
platform::containers::vector
std::vector< _type, _tAlloc > vector
Definition: Container.h:102
YSLib::NodeLiteral
包装节点的组合字面量。
Definition: ValueNode.h:1498
NPL
Definition: NPL/Configuration.h:35
platform::Descriptions::Warning
@ Warning
Definition: YCommon.h:183
platform::YB_NONNULL
YB_NONNULL(2) YB_PURE inline PDefH(std
组合消息和函数签名字符串。
Definition: Debug.h:560
CatchExpr
#define CatchExpr(_ex,...)
指定表达式作为异常处理器。
Definition: YBaseMacro.h:129
YSLib::LoadComponents
YF_API void LoadComponents(Application &, const ValueNode &)
初始化应用程序组件。
Definition: Initialization.cpp:707
platform
默认平台命名空间。
Definition: Container.h:56
range.hpp
范围操作。
YSLib
YSLib 命名空间。
Definition: AndroidHost.h:46
ystdex::fast_all_of
bool fast_all_of(_tIn first, _tIn last, _fPred pred)
快速序列判断操作。
Definition: algorithm.hpp:89
PathString
string PathString
Definition: Initialization.cpp:115
platform::ufexists
bool ufexists(const char *filename) ynothrowv
Definition: FileIO.cpp:947
YSLib::FetchLocalFHSRootPath
YB_ATTR_nodiscard YF_API YB_PURE const IO::Path & FetchLocalFHSRootPath()
取根路径字符串对应的局部 FHS 根路径。
Definition: Initialization.cpp:652
YSLib::LoadConfiguration
YF_API ValueNode LoadConfiguration(bool={})
载入默认配置。
Definition: Initialization.cpp:730
YSLib::Text::BOM_UTF_8
yconstexpr const char BOM_UTF_8[]
Definition: TextFile.h:70
YF_Helper_Initialization_FontDirectory_
#define YF_Helper_Initialization_FontDirectory_
Definition: Initialization.cpp:292
CHRLib::char16_t
YB_ATTR_nodiscard YB_PURE char16_t((*c_ptr<< CHAR_BIT)|c_ptr[1])) YB_ATTR_nodiscard YB_PURE inline PDefH(char16_t
取 c_ptr 指向的小端序双字节字符。
NPL::Session
会话：分析组成 NPL 基本翻译单元的源代码。
Definition: SContext.h:797
CatchRet
#define CatchRet(_ex,...)
指定返回语句作为异常处理器。
Definition: YBaseMacro.h:137
ystdex::to_string_d
_tSeqCon::value_type to_string_d(const path< _tSeqCon, _tTraits > &pth, typename string_traits< typename _tSeqCon::value_type >::value_type delimiter='/')
取以分隔符结束的字符串表示。
Definition: path.hpp:705
NPL::c_str
YF_API const char src c_str())) YF_API void InstallDirectory(const string &
安装目录：复制目录树。
Definition: Dependency.h:140
NPL::A1::LoadNode
YB_ATTR_nodiscard ValueNode LoadNode(_type &&tree, _tParams &&... args)
加载 NPLA1 翻译单元。
Definition: NPL/Configuration.h:48
platform::PDefH
YB_ATTR_nodiscard PDefH(string, MakePathString, u16string_view sv) ImplRet(MakePathString(sv.data())) using FileNodeID
文件节点标识类型。
mapped
MappedFile mapped
Definition: Initialization.cpp:316
platform::ynothrowv
YB_ATTR_nodiscard YF_API int amode ynothrowv
Definition: FileIO.h:550
YB_UNLIKELY
#define YB_UNLIKELY(_expr)
分支预测提示。
Definition: ydef.h:828
ystdex::byte
unsigned char byte
字节类型。
Definition: ydef.h:1283
platform::p
return p p
Definition: YCLib/FileSystem.h:209
YSLib::IO::MaxPathLength
yconstexpr const size_t MaxPathLength(yimpl(1<< 10))
默认目录路径长度。
const
const Decapsulate const Decapsulate &y ynothrow ContextNode &ctx const
Definition: NPLA1Forms.cpp:1629
ystdex::cpp2017::string
basic_string< char > string
Definition: string.hpp:772
YSLib::IO::VerifyDirectory
VerifyDirectory
Definition: YSLib/Service/FileSystem.h:524
platform_ex::Windows::FetchWindowsPath
YF_API wstring FetchWindowsPath(size_t=MAX_PATH)
取系统目录路径。
YSLib::LoadNPLA1File
ValueNode LoadNPLA1File(const char *disp, const char *path, ValueNode(*creator)(), bool show_info)
Definition: Initialization.cpp:693
TryRet
#define TryRet(...)
指定表达式在 try 块中求值并返回。
Definition: YBaseMacro.h:124
TryExpr
#define TryExpr(...)
指定表达式在 try 块中求值。
Definition: YBaseMacro.h:120
YSLib::IO::UniqueLockedOutputFileStream
独占锁定的文件输出流。
Definition: File.h:120
YB_ATTR_LAMBDA
#define YB_ATTR_LAMBDA(...)
允许在 lambda 表达式的参数列表后使用的属性。
Definition: ydef.h:581
YSLib::FetchRootPathString
YB_ATTR_nodiscard YF_API YB_PURE const string & FetchRootPathString()
取框架根路径字符串。
Definition: Initialization.cpp:669
NPL::SContext::Analyze
void Analyze(TermNode &root, const _tParseResult &parse_result)
分析指定源，取抽象语法树储存至指定值类型节点。
Definition: SContext.h:1127
YSLib::FatalError
致命错误。
Definition: YException.h:91
ystdex::cpp2017::begin
auto begin(_tRange &c) -> decltype(c.begin())
Definition: range.hpp:323
YSLib::creator
YB_ATTR_nodiscard YF_API const char ValueNode(* creator)()
Definition: Initialization.h:116
platform::Descriptions::Debug
@ Debug
Definition: YCommon.h:186
platform::strings::string
basic_string< char > string
Definition: Container.h:178
algorithm.hpp
泛型算法。