YSTest  PreAlpha_b500_20140530
The YSLib Test Project
 全部  命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 宏定义  
Initialization.cpp
浏览该文件的文档.
1 /*
2  © 2009-2014 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
30 #include YFM_YSLib_Core_YApplication
31 #include YFM_Helper_GUIApplication
32 #include YFM_YCLib_Debug
33 #include YFM_CHRLib_MappingEx
34 #include YFM_YCLib_MemoryMapping
35 #include YFM_YSLib_Service_FileSystem
36 #include <cstring> // for std::strcmp;
37 //#include <clocale>
38 #include YFM_NPL_SContext
39 
40 using namespace ystdex;
41 using namespace platform;
42 using std::puts;
43 
44 namespace YSLib
45 {
46 
47 using namespace Drawing;
48 using namespace IO;
49 
50 namespace
51 {
52 
54 
55 stack<std::function<void()>> app_exit;
56 ValueNode* p_root;
57 Drawing::FontCache* p_font_cache;
59 #if !CHRLIB_NODYNAMIC_MAPPING
60 platform::MappedFile* p_mapped;
62 #endif
63 MIMEBiMapping* p_mapping;
66 const char TU_MIME[]{u8R"NPLA1(
67 (application
68  (octet-stream "bin" "so")
69  (x-msdownload "exe" "dll" "com" "bat" "msi")
70  (x-font-ttf "ttf" "ttc")
71  (xml "xml")
72  (zip "zip")
73 )
74 (audio
75  (midi "mid" "midi" "rmi")
76  (mpeg "mp3")
77  (x-mpegurl "m3u")
78  (x-wav "wav")
79 )
80 (image
81  (bmp "bmp")
82  (gif "gif")
83  (jpeg "jpeg" "jpg")
84  (png "png")
85  (tif "tif" "tiff")
86 )
87 (text
88  (html "html" "htm")
89  (plain "txt" "conf" "def" "ini" "log" "in")
90  (x-c "c" "h" "inl")
91  (x-c++ "cc" "cpp" "cxx" "h" "hh" "hpp" "hxx" "inl")
92 )
93 )NPLA1"};
94 
95 #if YCL_DS
96 # define ROOTW
97 # define DATA_DIRECTORY ROOTW "/Data/"
98  //const char* DEF_FONT_NAME = ROOTW "方正姚体";
99  //const char* DEF_FONT_PATH = ROOTW "/Font/FZYTK.TTF";
100 # define DEF_FONT_PATH ROOTW "/Font/FZYTK.TTF"
101 # define DEF_FONT_DIRECTORY ROOTW "/Font/"
102 #else
103 # define ROOTW "."
104 # define DATA_DIRECTORY ROOTW "\\"
105  //const char* DEF_FONT_NAME = "方正姚体";
106  //const char* DEF_FONT_PATH = ROOTW "\\Font\\FZYTK.TTF";
107 # define DEF_FONT_PATH "C:\\Windows\\Fonts\\SimSun.ttc"
108 # define DEF_FONT_DIRECTORY ROOTW "\\"
109 #endif
110 #define CONF_PATH "yconf.txt"
111 
112 void
113 LoadComponents(const ValueNode& node)
114 {
115  const auto& data_dir(AccessChild<string>(node, "DataDirectory"));
116  const auto& font_path(AccessChild<string>(node, "FontFile"));
117  const auto& font_dir(AccessChild<string>(node, "FontDirectory"));
118 
119  if(!data_dir.empty() && !font_path.empty() && !font_dir.empty())
120  std::printf("Loaded default directory:\n%s\n"
121  "Loaded default font path:\n%s\n"
122  "Loaded default font directory:\n%s\n",
123  data_dir.c_str(), font_path.c_str(), font_dir.c_str());
124  else
125  throw LoggedEvent("Empty path loaded.");
126 #if !CHRLIB_NODYNAMIC_MAPPING
127  puts("Load character mapping file...");
128  p_mapped = new MappedFile(data_dir + "cp113.bin");
129  if(p_mapped->GetSize() != 0)
130  CHRLib::cp113 = p_mapped->GetPtr();
131  else
132  throw LoggedEvent("CHRMapEx loading fail.");
133  puts("CHRMapEx loaded successfully.");
134 #endif
135  std::printf("Trying entering directory %s ...\n", data_dir.c_str());
136  if(!IO::VerifyDirectory(data_dir))
137  throw LoggedEvent("Invalid default data directory found.");
138  if(!(ufexists(font_path) || IO::VerifyDirectory(font_dir)))
139  throw LoggedEvent("Invalid default font file path found.");
140 }
141 
142 } // unnamed namespace;
143 
144 void
146 {
147  YDebugSetStatus();
148  YDebugBegin();
149 
150  const char* line("--------------------------------");
151 
152  std::printf("%s%s%s\n%s\n%s",
153  line, e.GetTitle(), line, e.GetContent(), line);
154  terminate();
155 }
156 
157 
158 ValueNode
159 LoadNPLA1File(const char* disp, const char* path, ValueNode(*creator)(),
160  bool show_info)
161 {
162  if(!ufexists(path))
163  {
164  if(show_info)
165  std::printf("Creating %s '%s'...\n", disp, path);
166  if(creator)
167  {
168  if(TextFile tf{path, std::ios_base::out | std::ios_base::trunc})
169  tf << NPL::Configuration(creator());
170  else
171  throw LoggedEvent("Cannot create file.");
172  }
173  else
174  return {};
175  }
176 
177  TextFile tf(path);
178 
179  if(show_info)
180  std::printf("Found %s '%s'.\n", disp, path);
181  return ReadConfiguration(tf);
182 }
183 
184 
185 ValueNode
187 {
188  if(YB_LIKELY(tf))
189  {
191  throw LoggedEvent("Wrong encoding of configuration file.");
192 
193  NPL::Configuration conf;
194 
195  tf >> conf;
196  if(conf.GetNodeRRef().GetSize() != 0)
197  return conf.GetNodeRRef();
198  }
199  throw LoggedEvent("Invalid file found when reading configuration.");
200 }
201 
202 void
204 {
205  if(YB_UNLIKELY(!tf))
206  throw LoggedEvent("Invalid file found when writing configuration.");
207  tf << NPL::Configuration("", node.Value);
208 }
209 
210 ValueNode
211 LoadConfiguration(bool show_info)
212 {
213  return LoadNPLA1File("configuration file", CONF_PATH, []{
214  return PackNodes("YFramework", MakeNode("DataDirectory",
215  string(DATA_DIRECTORY)), MakeNode("FontFile",
216  string(DEF_FONT_PATH)), MakeNode("FontDirectory",
217  string(DEF_FONT_DIRECTORY)));
218  }, show_info);
219 }
220 
221 void
223 {
224  TextFile tf(CONF_PATH, std::ios_base::out | std::ios_base::trunc);
225 
226  WriteConfiguration(tf, node);
227 }
228 
229 
230 void
232 {
233  //设置默认异常终止函数。
234  std::set_terminate(terminate);
235 #if YCL_DS
236  //启用设备。
237  ::powerOn(POWER_ALL);
238 
239  //启用 LibNDS 默认异常处理。
240  ::defaultExceptionHandler();
241 
242  //初始化主控制台。
243  platform::YConsoleInit(true, ColorSpace::Lime);
244 
245  //初始化文件系统。
246  //初始化 EFSLib 和 LibFAT 。
247  //当 .nds 文件大于32MB时, EFS 行为异常。
248 # ifdef USE_EFS
249  if(!::EFS_Init(EFS_AND_FAT | EFS_DEFAULT_DEVICE, nullptr))
250  {
251  //如果初始化 EFS 失败则初始化 FAT 。
252 # endif
253  if(!::fatInitDefault())
254  throw FatalError(" LibFAT Failure ",
255  " An error is preventing the\n"
256  " program from accessing\n"
257  " external files.\n"
258  "\n"
259  " If you're using an emulator,\n"
260  " make sure it supports DLDI\n"
261  " and that it's activated.\n"
262  "\n"
263  " In case you're seeing this\n"
264  " screen on a real DS, make sure\n"
265  " you've applied the correct\n"
266  " DLDI patch (most modern\n"
267  " flashcards do this\n"
268  " automatically).\n"
269  "\n"
270  " Note: Some cards only\n"
271  " autopatch .nds files stored in\n"
272  " the root folder of the card.\n");
273 # ifdef USE_EFS
274  }
275 # endif
276 #endif
277 #if 0
278  // TODO: Review locale APIs compatibility.
279  static yconstexpr char locale_str[]{"zh_CN.GBK"};
280 
281  if(!std::setlocale(LC_ALL, locale_str))
282  throw LoggedEvent("Call of std::setlocale() with %s failed.\n",
283  locale_str);
284 #endif
285 }
286 
287 ValueNode
289 {
290  puts("Checking installation...");
291  try
292  {
293  auto node(LoadConfiguration(true));
294 
295  if(node.GetName() == "YFramework")
296  node = PackNodes("", std::move(node));
297  LoadComponents(node.at("YFramework"));
298  puts("OK!");
299  return node;
300  }
301  catch(std::exception& e)
302  {
303  std::printf("Error occurred: %s\n", e.what());
304  }
305  throw FatalError(" Invalid Installation ",
306  " Please make sure the data is\n"
307  " stored in correct directory.\n");
308 }
309 
310 void
311 InitializeSystemFontCache(FontCache& fc, const string& fong_file,
312  const string& font_dir)
313 {
314  puts("Loading font files...");
315  try
316  {
317  size_t nFileLoaded(fc.LoadTypefaces(fong_file) != 0);
318 
319  if(!font_dir.empty())
320  //读取字体文件目录并载入目录下指定后缀名的字体文件。
321  try
322  {
323  HDirectory dir{font_dir.c_str()};
324  IO::PathNorm nm;
325 
326  std::for_each(FileIterator(&dir), FileIterator(),
327  [&](const std::string& name){
328  if(!nm.is_self(name)
329  && dir.GetNodeCategory() != NodeCategory::Directory
330  /*&& IsExtensionOf(ext, dir.GetName())*/)
331  {
332  FontPath path(font_dir + dir.GetName());
333 
334  if(path != fong_file)
335  nFileLoaded += fc.LoadTypefaces(path) != 0;
336  }
337  });
338  }
339  catch(FileOperationFailure&)
340  {}
342  if(const auto nFaces = fc.GetFaces().size())
343  std::printf("%u face(s) in %u font file(s)"
344  " are loaded\nsuccessfully.\n", nFaces, nFileLoaded);
345  else
346  throw LoggedEvent("No fonts found.");
347  puts("Setting default font face...");
348  if(const auto* const pf = fc.GetDefaultTypefacePtr())
349  std::printf("\"%s\":\"%s\",\nsuccessfully.\n",
350  pf->GetFamilyName().c_str(), pf->GetStyleName().c_str());
351  else
352  throw LoggedEvent("Setting default font face failed.");
353  return;
354  }
355  // TODO: Use %std::nested_exception.
356  catch(std::exception& e)
357  {
358  puts(e.what());
359  }
360  throw FatalError(" Font Caching Failure ",
361  " Please make sure the fonts are\n"
362  " stored in correct path.\n");
363 }
364 
365 void
367 {
368  while(!app_exit.empty())
369  {
370  if(YB_LIKELY(app_exit.top()))
371  app_exit.top()();
372  app_exit.pop();
373  }
374 #if !CHRLIB_NODYNAMIC_MAPPING
375  delete p_mapped;
376 #endif
377 }
378 
379 
380 ValueNode&
382 {
383  if(YB_UNLIKELY(!p_root))
384  {
385  p_root = ynew ValueNode(InitializeInstalled());
386  app_exit.push([]{
387  ydelete(p_root);
388  });
389  }
390  return *p_root;
391 }
392 
393 Drawing::FontCache&
395 {
396  if(YB_UNLIKELY(!p_font_cache))
397  {
398  p_font_cache = ynew Drawing::FontCache;
399  app_exit.push([]{
400  ydelete(p_font_cache);
401  });
402 
403  const auto& node(FetchRoot()["YFramework"]);
404 
405  InitializeSystemFontCache(*p_font_cache,
406  AccessChild<string>(node, "FontFile"),
407  AccessChild<string>(node, "FontDirectory"));
408  }
409  return *p_font_cache;
410 }
411 
412 MIMEBiMapping&
414 {
415  if(YB_UNLIKELY(!p_mapping))
416  {
417  p_mapping = ynew MIMEBiMapping;
418  app_exit.push([]{
419  ydelete(p_mapping);
420  });
421  AddMIMEItems(*p_mapping, LoadNPLA1File("MIME database",
422  (AccessChild<string>(FetchRoot()["YFramework"], "DataDirectory")
423  + "MIMEExtMap.txt").c_str(), []{
424  return
426  }, true));
427  }
428  return *p_mapping;
429 }
430 
431 } // namespace YSLib;
432 
会话:分析指定 NPL 代码。
Definition: SContext.h:54
void InitializeDefaultTypeface()
初始化默认字型。
Definition: Font.cpp:486
YF_API ValueNode InitializeInstalled()
初始化已安装项:检查安装完整性并载入主配置文件的配置项。
设置:使用 S 表达式存储外部状态。
Definition: Configuration.h:49
Text::Encoding Encoding
编码。
Definition: TextFile.h:67
YF_API ValueNode & FetchRoot()
取值类型根节点。
YF_API void YDebugBegin()
调试模式:显示控制台。
Definition: Debug.cpp:75
一般路径模板。
Definition: path.hpp:149
YF_API ValueNode LoadNPLA1(ValueNode &&)
读取 NPLA1 翻译单元。
Definition: NPLA1.cpp:86
文本文件类。
Definition: TextFile.h:56
#define DEF_FONT_PATH
YF_API bool ufexists(const char *) ynothrow
判断指定 UTF-8 文件名的文件是否存在。
#define CONF_PATH
YF_API MIMEBiMapping & FetchMIMEBiMapping()
取 MIME 类型名和文件扩展名双向映射对象。
ValueNode PackNodes(_tString &&name, _tParams &&...args)
取以指定分量为参数对应初始化得到的值类型节点为子节点的值类型节点。
Definition: ValueNode.h:391
只读内存映射文件。
Definition: MemoryMapping.h:42
ValueObject Value
Definition: ValueNode.h:59
#define DEF_FONT_DIRECTORY
YF_API void Analyze(ValueNode &, const TokenList &)
分析指定源,取抽象语法树储存至指定值类型节点。
Definition: SContext.cpp:96
#define ynew
Definition: ynew.h:205
目录句柄:表示打开的目录和内容迭代状态。
YF_API void SaveConfiguration(const ValueNode &)
保存默认配置。
YF_API void YDebugSetStatus(bool=true)
调试模式:设置状态。
Definition: Debug.cpp:63
YB_NORETURN YF_API void terminate() ynothrow
异常终止函数。
Definition: ycommon.cpp:39
MIME 和文件扩展名双向映射。
Definition: ContentType.h:45
#define YB_UNLIKELY(expr)
分支预测提示。
Definition: ydef.h:298
文件路径范式。
YF_API ValueNode LoadConfiguration(bool={})
载入默认配置。
字体缓存。
Definition: Font.h:415
#define ynothrow
YSLib 无异常抛出保证:若支持 noexcept 关键字, 指定特定的 noexcept 异常规范。
Definition: ydef.h:514
yconstfn const string & name
Definition: Loader.h:110
YF_API Drawing::FontCache & FetchDefaultFontCache()
取默认字体缓存。
GSStringTemplate< char >::basic_string string
Definition: ycont.h:164
YF_API void YConsoleInit(std::uint8_t dspIndex, Color fc=ColorSpace::White, Color bc=ColorSpace::Black)
启动控制台。
值类型节点。
Definition: ValueNode.h:45
YF_API ValueNode LoadNPLA1File(const char *disp, const char *path, ValueNode(*creator)(), bool show_info={})
载入 NPLA1 配置文件。
YF_API ValueNode ReadConfiguration(TextFile &)
从文本文件中读取配置。
致命错误。
Definition: yexcept.h:87
YF_API void InitializeSystemFontCache(Drawing::FontCache &, const string &, const string &)
初始化系统字体缓存。
ystdex::indirect_input_iterator< HDirectory * > FileIterator
文件迭代器。
#define ydelete
Definition: ynew.h:207
virtual bool is_self(const value_type &)=0
YF_API void AddMIMEItems(MIMEBiMapping &, const ValueNode &, MIMEBiMapping::MIMEType &&={})
根据 NPLA1 节点内容增加 MIME 映射。
Definition: ContentType.cpp:62
YF_API void Uninitialize() ynothrow
反初始化。
YB_NORETURN YF_API void HandleFatalError(const FatalError &) ynothrow
处理致命错误:显示错误信息并终止程序。
size_t LoadTypefaces(const FontPath &)
从字体文件组中载入字型信息。
Definition: Font.cpp:456
YF_API void InitializeEnviornment()
初始化环境。
记录日志的异常事件类。
Definition: yexcept.h:58
#define yconstexpr
指定编译时常量表达式。
Definition: ydef.h:462
std::string FontPath
字体文件路径。
Definition: Font.h:68
YF_API void WriteConfiguration(TextFile &, const ValueNode &)
写入配置至文本文件。
byte * cp113
Definition: MapEx.cpp:39
#define DATA_DIRECTORY
表示文件操作失败的异常。
#define YB_LIKELY(expr)
Definition: ydef.h:297
yconstexpr Encoding UTF_8(csUTF8)
const Typeface * GetDefaultTypefacePtr() const
取默认字型指针。
Definition: Font.cpp:408