1 /**
2  * SDLang Loader
3  *
4  * Copyright: (c) 2015-2016, Milofon Project.
5  * License: Subject to the terms of the BSD license, as written in the included LICENSE.txt file.
6  * Authors: Maksim Galanin
7  */
8 module proped.loaders.sdl;
9 
10 version(Have_sdlang_d):
11 
12 private
13 {
14     import std.array : empty;
15 
16     import sdlang;
17 
18     import proped.properties : Properties, PropNode;
19     import proped.loader : PropertiesLoader;
20     import proped.exception : PropertiesException;
21     import proped.uninode : isArray, toArray;
22 }
23 
24 
25 
26 /**
27  * The loader data from a SDLang file
28  *
29  * Implements PropertiesLoader
30  */
31 class SDLPropertiesLoader : PropertiesLoader 
32 {
33     /**
34      * Loading properties from a file
35      *
36      * Params:
37      *
38      * fileName = Path to the file system
39      */
40     Properties loadPropertiesFile(string fileName)
41     {
42         Tag root;
43 
44         try 
45             root = parseFile(fileName);
46         catch(ParseException e)
47             throw new PropertiesException("Error loading properties from a file '" ~ fileName ~ "':", e);
48 
49         return toProperties(root);
50     }
51 
52 
53     /**
54      * Loading properties from a string
55      *
56      * Params:
57      *
58      * data = Source string
59      */
60     Properties loadPropertiesString(string data)
61     {
62         Tag root;
63 
64         try
65             root = parseSource(data);
66         catch(ParseException e)
67             throw new PropertiesException("Error loading properties from string:", e);
68 
69         return toProperties(root);
70     }
71 
72 
73     private Properties toProperties(Tag root)
74     {
75         PropNode convertVal(Value val)
76         {
77             if (val.convertsTo!bool)
78                 return PropNode(val.get!bool);
79             else if (val.convertsTo!long)
80                 return PropNode(val.get!long);
81             else if (val.convertsTo!string)
82                 return PropNode(val.get!string);
83             else if (val.convertsTo!double)
84                 return PropNode(val.get!double);
85             else
86                 return PropNode();
87         }
88 
89         PropNode convert(Tag tag)
90         {
91             if (!tag.tags.empty || !tag.attributes.empty)
92             {
93                 PropNode[string] map;
94                 if (!tag.values.empty && tag.values[0].convertsTo!string)
95                     map["name"] = convertVal(tag.values[0]);
96 
97                 if (!tag.attributes.empty)
98                     foreach(Attribute a; tag.attributes)
99                         map[a.name] = convertVal(a.value);
100 
101                 if (!tag.tags.empty)
102                     foreach(Tag sub; tag.tags)
103                     {
104                         PropNode res = convert(sub);
105                         if (!res.hasValue)
106                             continue;
107 
108                         if (sub.name in map)
109                         {
110                             PropNode origin = map[sub.name];
111                             if (origin.isArray) 
112                                 map[sub.name] = origin.toArray ~ res;
113                             else
114                             {
115                                 PropNode[] arr = [origin, res];
116                                 map[sub.name] = arr;
117                             }
118                         }
119                         else
120                             map[sub.name] = res;
121                     }
122                 return PropNode(map);
123             }
124             else if (tag.values.length == 1)
125             {
126                 return convertVal(tag.values[0]);
127             }
128             else if (tag.values.length > 0)
129             {
130                 PropNode[] arr;
131                 foreach (Value v; tag.values)
132                     arr ~= convertVal(v);
133                 return PropNode(arr);
134             }
135             else
136                 return PropNode(); 
137         }
138 
139         return Properties(convert(root));
140     }
141 
142 
143     /**
144      * Returns the file extension to delermite the type loader
145      */
146     string[] getExtensions()
147     {
148         return [".sdl"];
149     }
150 }
151