Browse Source

Initialise Lua Units

Peter Colberg 5 years ago
commit
4e9d683d3b
19 changed files with 1165 additions and 0 deletions
  1. 3
    0
      .gitignore
  2. 19
    0
      LICENSE
  3. 30
    0
      Makefile
  4. 49
    0
      doc/INSTALL.mdwn
  5. 19
    0
      doc/Makefile
  6. 10
    0
      doc/contents.mdwn
  7. 13
    0
      doc/index.mdwn
  8. BIN
      doc/lua-units.png
  9. 210
    0
      doc/lua-units.ps
  10. 255
    0
      doc/pandoc.css
  11. 72
    0
      doc/pandoc.html.in
  12. 83
    0
      doc/reference.mdwn
  13. 35
    0
      test/.luacov
  14. 26
    0
      test/Makefile
  15. 48
    0
      test/unit.lua
  16. 91
    0
      units/C.c
  17. 23
    0
      units/C.lua.in
  18. 36
    0
      units/Makefile
  19. 143
    0
      units/init.lua

+ 3
- 0
.gitignore View File

@@ -0,0 +1,3 @@
1
+/doc/*.html
2
+/units/C.lua
3
+/test/*.out

+ 19
- 0
LICENSE View File

@@ -0,0 +1,19 @@
1
+Copyright © 2013 Peter Colberg.
2
+
3
+Permission is hereby granted, free of charge, to any person obtaining a copy
4
+of this software and associated documentation files (the "Software"), to deal
5
+in the Software without restriction, including without limitation the rights
6
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+copies of the Software, and to permit persons to whom the Software is
8
+furnished to do so, subject to the following conditions:
9
+
10
+The above copyright notice and this permission notice shall be included in
11
+all copies or substantial portions of the Software.
12
+
13
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
16
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+THE SOFTWARE.

+ 30
- 0
Makefile View File

@@ -0,0 +1,30 @@
1
+#
2
+# Lua Units.
3
+# Copyright © 2013 Peter Colberg.
4
+# For conditions of distribution and use, see copyright notice in LICENSE.
5
+#
6
+
7
+PREFIX = /usr/local
8
+
9
+INSTALL_LMOD = $(PREFIX)/share/lua/5.1/units
10
+INSTALL_DIR = mkdir -p
11
+INSTALL_DATA = install -m 644
12
+
13
+FILES_LMOD = C.lua init.lua
14
+
15
+units:
16
+	@$(MAKE) -C units
17
+
18
+test: units
19
+	@$(MAKE) -C test
20
+
21
+install: units
22
+	$(INSTALL_DIR) $(DESTDIR)$(INSTALL_LMOD)
23
+	cd units && $(INSTALL_DATA) $(FILES_LMOD) $(DESTDIR)$(INSTALL_LMOD)
24
+
25
+clean:
26
+	@$(MAKE) -C units clean
27
+	@$(MAKE) -C test clean
28
+	@$(MAKE) -C doc clean
29
+
30
+.PHONY: units test install clean

+ 49
- 0
doc/INSTALL.mdwn View File

@@ -0,0 +1,49 @@
1
+% Installing
2
+
3
+Lua Units is available from a [git repository]:
4
+
5
+~~~
6
+git clone http://git.colberg.org/lua-units
7
+~~~
8
+
9
+[git repository]: http://git.colberg.org/lua-units
10
+
11
+Before using the module, generate matching FFI C bindings for the udunits2
12
+library using the [Lua plugin for GCC] and the [C declaration composer]:
13
+
14
+~~~
15
+make
16
+~~~
17
+
18
+[Lua plugin for GCC]: http://colberg.org/gcc-lua/INSTALL.html
19
+[C declaration composer]: http://colberg.org/gcc-lua-cdecl/INSTALL.html
20
+
21
+To override the default C compiler `gcc`, set `CC`:
22
+
23
+~~~
24
+make CC=gcc-4.7
25
+~~~
26
+
27
+If the udunits2 header files are not installed in a system path, set CPATH:
28
+
29
+~~~
30
+CPATH=/opt/udunits2/include make
31
+~~~
32
+
33
+To override the name of the udunits2 library, set `LIBNAME`:
34
+
35
+~~~
36
+make LIBNAME=libudunits2.so.0
37
+~~~
38
+
39
+The module is accompanied by a test suite:
40
+
41
+~~~
42
+make test
43
+~~~
44
+
45
+To install the module to the default Lua path:
46
+
47
+~~~
48
+make install
49
+~~~

+ 19
- 0
doc/Makefile View File

@@ -0,0 +1,19 @@
1
+html: index.html INSTALL.html reference.html
2
+
3
+%.html: %.mdwn pandoc.html
4
+	pandoc --template=pandoc.html --css=pandoc.css --toc -o $@ $<
5
+
6
+index.html: index.mdwn pandoc.html
7
+	pandoc --template=pandoc.html --css=pandoc.css -V pagetitle= -o $@ $<
8
+
9
+pandoc.html: contents.mdwn pandoc.html.in
10
+	pandoc --template=pandoc.html.in -o $@ $<
11
+
12
+%.png: %.ps
13
+	convert -resize 128x128 -strip $< $@
14
+	optipng $@
15
+
16
+clean:
17
+	$(RM) *.html
18
+
19
+.INTERMEDIATE: pandoc.html

+ 10
- 0
doc/contents.mdwn View File

@@ -0,0 +1,10 @@
1
+% Lua Units
2
+% Peter Colberg
3
+% 2013
4
+
5
+[![](lua-units.png "Lua Units")](index.html)
6
+
7
+* [Lua Units](index.html)
8
+    + [Installing](INSTALL.html)
9
+    + [Reference](reference.html)
10
+    + [Mailing list](https://lists.colberg.org/listinfo/lua-units)

+ 13
- 0
doc/index.mdwn View File

@@ -0,0 +1,13 @@
1
+% About Lua Units
2
+
3
+[Lua Units] provides bindings for [UDUNITS-2], a package that provides support
4
+for units of physical quantities. [Lua] is a powerful, fast, lightweight, and
5
+embeddable scripting language. [LuaJIT] is a just-in-time compiler for the Lua
6
+language, which allows using native C data structures as part of its foreign
7
+function interface library ([FFI]).
8
+
9
+[Lua Units]: http://colberg.org/lua-units/
10
+[UDUNITS-2]: http://www.unidata.ucar.edu/software/udunits/udunits-2/udunits2.html
11
+[Lua]: http://www.lua.org/about.html
12
+[LuaJIT]: http://luajit.org/luajit.html
13
+[FFI]: http://luajit.org/ext_ffi.html

BIN
doc/lua-units.png View File


+ 210
- 0
doc/lua-units.ps View File

@@ -0,0 +1,210 @@
1
+%!PS-Adobe-2.0 EPSF-2.0
2
+%%Title: Lua logo
3
+%%Creator: lua@tecgraf.puc-rio.br
4
+%%CreationDate: Wed Nov 29 19:04:04 EDT 2000
5
+%%BoundingBox: -45 0 1035 1080
6
+%%Pages: 1
7
+%%EndComments
8
+%%EndProlog
9
+
10
+%------------------------------------------------------------------------------
11
+%
12
+% Graphic design by Alexandre Nakonechnyj.
13
+% PostScript programming by the Lua team.
14
+% This code is hereby placed in the public domain.
15
+%
16
+% Permission is hereby granted, without written agreement and without license
17
+% or royalty fees, to use, copy, and distribute this logo for any purpose,
18
+% including commercial applications, subject to the following conditions:
19
+%
20
+% * The origin of this logo must not be misrepresented; you must not
21
+%   claim that you drew the original logo. We recommend that you give credit
22
+%   to the graphics designer in all printed matter that includes the logo.
23
+%
24
+% * The only modification you can make is to adapt the orbiting text to
25
+%   your product name.
26
+%
27
+% * The logo can be used in any scale as long as the relative proportions
28
+%   of its elements are maintained.
29
+%
30
+%------------------------------------------------------------------------------
31
+
32
+/LABEL		(Lua Units) def
33
+
34
+%-- DO NOT CHANGE ANYTHING BELOW THIS LINE ------------------------------------
35
+
36
+/PLANETCOLOR	{0 0 0.5 setrgbcolor} bind def
37
+/HOLECOLOR	{1.0 setgray} bind def
38
+/ORBITCOLOR	{0.5 setgray} bind def
39
+/LOGOFONT	{/Helvetica 0.90} def
40
+/LABELFONT	{/Helvetica 0.36} def
41
+
42
+%------------------------------------------------------------------------------
43
+
44
+/MOONCOLOR	{PLANETCOLOR} bind def
45
+/LOGOCOLOR	{HOLECOLOR} bind def
46
+/LABELCOLOR	{ORBITCOLOR} bind def
47
+
48
+/LABELANGLE	125 def
49
+/LOGO		(Lua) def
50
+
51
+/DASHANGLE	10 def
52
+/HALFDASHANGLE	DASHANGLE 2 div def
53
+
54
+% moon radius. planet radius is 1.
55
+/r 1 2 sqrt 2 div sub def
56
+
57
+/D {0 360 arc fill} bind def
58
+/F {exch findfont exch scalefont setfont} bind def
59
+
60
+% place it nicely on the paper
61
+/RESOLUTION	1024 def
62
+RESOLUTION 2 div dup translate
63
+RESOLUTION 2 div 2 sqrt div dup scale
64
+
65
+%-------------------------------------------------------------------- planet --
66
+PLANETCOLOR
67
+0 0 1 D
68
+
69
+%---------------------------------------------------------------------- hole --
70
+HOLECOLOR
71
+1 2 r mul sub dup r D
72
+
73
+%---------------------------------------------------------------------- moon --
74
+MOONCOLOR
75
+1 1 r D
76
+
77
+%---------------------------------------------------------------------- logo --
78
+LOGOCOLOR
79
+LOGOFONT
80
+F
81
+LOGO stringwidth pop 2 div neg
82
+-0.5 moveto
83
+LOGO show
84
+
85
+%------------------------------------------------------------------------------
86
+% based on code from Blue Book Program 10, on pages 167--169
87
+% available at ftp://ftp.adobe.com/pub/adobe/displaypostscript/bluebook.shar
88
+
89
+%	str ptsize centerangle radius	outsidecircletext	--
90
+/outsidecircletext {
91
+	circtextdict begin
92
+	/radius exch def
93
+	/centerangle exch def
94
+	/ptsize exch def
95
+	/str exch def
96
+
97
+	gsave
98
+	 str radius ptsize findhalfangle
99
+	 centerangle
100
+	 add rotate
101
+	 str
102
+		{ /charcode exch def
103
+		  ( ) dup 0 charcode put outsideplacechar
104
+		} forall
105
+	
106
+	grestore
107
+	end
108
+} def
109
+
110
+%	string radius ptsize	findhalfangle	halfangle
111
+/findhalfangle {
112
+	4 div add
113
+	exch
114
+	stringwidth pop 2 div
115
+	exch
116
+	2 mul 3.1415926535 mul div 360 mul
117
+} def
118
+
119
+/circtextdict 16 dict def
120
+circtextdict begin
121
+
122
+ /outsideplacechar {
123
+	/char exch def
124
+	/halfangle char radius ptsize findhalfangle def
125
+	gsave
126
+	 halfangle neg rotate
127
+	 radius 0 translate
128
+	 -90 rotate
129
+	 char stringwidth pop 2 div neg 0 moveto
130
+	 char show
131
+	grestore
132
+	halfangle 2 mul neg rotate
133
+ } def
134
+
135
+end
136
+
137
+%--------------------------------------------------------------------- label --
138
+LABELFONT
139
+F
140
+
141
+/LABELSIZE	LABELFONT exch pop def
142
+/LABELRADIUS	LABELSIZE 3 div 1 r add sub neg 1.02 mul def
143
+
144
+
145
+/HALFANGLE
146
+	LABEL LABELRADIUS LABELSIZE findhalfangle
147
+	HALFDASHANGLE div ceiling HALFDASHANGLE mul
148
+def
149
+
150
+/LABELANGLE
151
+	60 LABELANGLE HALFANGLE sub
152
+	lt
153
+	{
154
+	HALFANGLE
155
+	HALFANGLE DASHANGLE div floor DASHANGLE mul
156
+	eq
157
+		{LABELANGLE DASHANGLE div ceiling DASHANGLE mul}
158
+		{LABELANGLE HALFDASHANGLE sub DASHANGLE div round DASHANGLE mul HALFDASHANGLE add}
159
+	ifelse
160
+	}
161
+	{HALFANGLE 60 add}
162
+	ifelse
163
+def
164
+
165
+LABELCOLOR
166
+LABEL
167
+LABELSIZE
168
+LABELANGLE
169
+LABELRADIUS
170
+outsidecircletext
171
+
172
+%--------------------------------------------------------------------- orbit --
173
+ORBITCOLOR
174
+0.03 setlinewidth
175
+[1 r add 3.1415926535 180 div HALFDASHANGLE mul mul] 0 setdash
176
+newpath
177
+0 0
178
+1 r add
179
+3 copy
180
+30
181
+LABELANGLE HALFANGLE add
182
+arcn
183
+stroke
184
+60
185
+LABELANGLE HALFANGLE sub
186
+2 copy
187
+lt {arc stroke} {4 {pop} repeat} ifelse
188
+
189
+%------------------------------------------------------------------ copyright --
190
+/COPYRIGHT
191
+(Graphic design by A. Nakonechnyj. Copyright (c) 1998, All rights reserved.)
192
+def
193
+
194
+LABELCOLOR
195
+LOGOFONT
196
+32 div
197
+F
198
+2 sqrt 0.99 mul
199
+dup
200
+neg
201
+moveto
202
+COPYRIGHT
203
+90 rotate
204
+%show
205
+
206
+%---------------------------------------------------------------------- done --
207
+showpage
208
+
209
+%%Trailer
210
+%%EOF

+ 255
- 0
doc/pandoc.css View File

@@ -0,0 +1,255 @@
1
+/*
2
+ * Stylesheet for Pandoc.
3
+ * Copyright © 2013 Peter Colberg.
4
+ * For conditions of distribution and use, see copyright notice in LICENSE.
5
+ */
6
+
7
+/*
8
+ * I would like to acknowledge Eric Pierce and Eric Holscher for their
9
+ * beautiful design seen at http://read-the-docs.readthedocs.org/.
10
+ */
11
+
12
+body {
13
+  font: 100%/1.5 'Arial', 'Helvetica', sans-serif;
14
+  color: #fff;
15
+  background-color: #4759a7;
16
+  margin: 0;
17
+  padding: 0;
18
+}
19
+
20
+div.header ul {
21
+  display: table;
22
+  list-style: none;
23
+  margin: 0;
24
+  padding: 0 0 0 10px;
25
+  height: 2.5em;
26
+}
27
+
28
+div.header ul li {
29
+  display: table-cell;
30
+  vertical-align: middle;
31
+}
32
+
33
+div.header ul li a {
34
+  font-weight: bold;
35
+  color: #fff;
36
+  text-shadow: 0 1px rgba(0, 0, 0, 0.5);
37
+  margin: 0 0 0 4px;
38
+  padding: 3px 6px;
39
+  border: none;
40
+  border-radius: 3px;
41
+}
42
+
43
+div.header ul li a:hover {
44
+  background-color: #7a8ad1;
45
+  border-radius: 3px;
46
+}
47
+
48
+div.columns {
49
+  display: table;
50
+  table-layout: fixed;
51
+  width: 100%;
52
+  color: #000;
53
+}
54
+
55
+div.columns div {
56
+  display: table-cell;
57
+  vertical-align: top;
58
+}
59
+
60
+div.sidebar {
61
+  background-color: #e8e9ef;
62
+  width: 12em;
63
+}
64
+
65
+div.sidebar ul {
66
+  list-style: none;
67
+  font-size: 1em;
68
+  margin: 1em;
69
+  padding: 0;
70
+}
71
+
72
+div.sidebar ul ul {
73
+  margin: 0;
74
+}
75
+
76
+div.sidebar ul ul ul {
77
+  margin-left: 1em;
78
+}
79
+
80
+div.sidebar a {
81
+  border-bottom: none;
82
+}
83
+
84
+div.sidebar ul ul li {
85
+  overflow: hidden;
86
+  white-space: nowrap;
87
+  text-overflow: ellipsis;
88
+  position: relative;
89
+}
90
+
91
+div.sidebar ul ul li:hover {
92
+  overflow: visible;
93
+}
94
+
95
+div.sidebar ul li a {
96
+  font-weight: bold;
97
+  color: #444;
98
+}
99
+
100
+div.sidebar ul li a:hover {
101
+  color: #111;
102
+  border-bottom: 1px solid #111;
103
+}
104
+
105
+div.sidebar ul ul li a {
106
+  font-weight: normal;
107
+  background-color: #e8e9ef;
108
+  padding: 0 5px;
109
+  border: 1px solid transparent;
110
+  border-radius: 3px;
111
+}
112
+
113
+div.sidebar ul ul li a:hover {
114
+  border: 1px solid #888;
115
+}
116
+
117
+div.sidebar p {
118
+  text-align: center;
119
+}
120
+
121
+div.body {
122
+  background-color: #fff;
123
+  padding: 0.5em 1.3em;
124
+  border-left: 1px solid #ccc;
125
+  border-bottom: 1px solid #ccc;
126
+}
127
+
128
+div.footer {
129
+  font-size: 0.8em;
130
+  color: #fff;
131
+  text-align: center;
132
+  padding: 0 2em 2em 2em;
133
+}
134
+
135
+div.footer a {
136
+  color: #fff;
137
+}
138
+
139
+div.footer a:hover {
140
+  border-bottom: 1px solid #7a8ad1;
141
+}
142
+
143
+a {
144
+  color: #444;
145
+  text-decoration: none;
146
+  border-bottom: 1px solid #ccc;
147
+}
148
+
149
+a:hover {
150
+  color: #111;
151
+  text-decoration: none;
152
+  border-bottom: 1px solid #111;
153
+}
154
+
155
+a:focus {
156
+  outline: none;
157
+}
158
+
159
+h1 {
160
+  margin: 0;
161
+  padding: 0.7em 0 0.3em 0;
162
+  font-size: 1.5em;
163
+  line-height: 1.15;
164
+  color: #111;
165
+}
166
+
167
+h1 a {
168
+  color: #111;
169
+  border-bottom: none;
170
+}
171
+
172
+h2 {
173
+  margin: 2em 0 1em 0;
174
+  font-size: 1.35em;
175
+  padding: 0;
176
+  color: #465158;
177
+}
178
+
179
+h2 a {
180
+  color: #465158;
181
+  border-bottom: none;
182
+}
183
+
184
+h3 {
185
+  margin: 1em 0 0.8em 0;
186
+  font-size: 1.2em;
187
+  color: #6c818f;
188
+}
189
+
190
+h3 a {
191
+  color: #6c818f;
192
+  border-bottom: none;
193
+}
194
+
195
+h4 {
196
+  margin: 1em 0 0.8em 0;
197
+  font-size: 1.1em;
198
+  color: #6c818f;
199
+}
200
+
201
+h4 a {
202
+  color: #6c818f;
203
+  border-bottom: none;
204
+}
205
+
206
+div.body p {
207
+  margin-top: 0.5em;
208
+  margin-bottom: 1em;
209
+}
210
+
211
+cite, code, dt, pre {
212
+  font-family: 'Consolas', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
213
+}
214
+
215
+cite, code {
216
+  font-size: 0.95em;
217
+}
218
+
219
+dl {
220
+  margin: 0;
221
+  padding: 0;
222
+}
223
+
224
+dt {
225
+  font-weight: bold;
226
+  color: #444;
227
+}
228
+
229
+dt code {
230
+  font: inherit;
231
+  font-size: 1em;
232
+}
233
+
234
+pre {
235
+  font-size: 0.85em;
236
+  line-height: 120%;
237
+  margin: 1em 2em;
238
+  padding: 0.5em;
239
+  border: 1px solid #ccc;
240
+  background-color: #e8e9ef;
241
+  border-radius: 6px;
242
+  overflow: hidden;
243
+  text-overflow: ellipsis;
244
+}
245
+
246
+pre code {
247
+  font-size: 1em;
248
+}
249
+
250
+table {
251
+  width: 100%;
252
+  margin: 1em 0;
253
+  border-spacing: 0;
254
+  border-collapse: collapse;
255
+}

+ 72
- 0
doc/pandoc.html.in View File

@@ -0,0 +1,72 @@
1
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+<html xmlns="http://www.w3.org/1999/xhtml"$$if(lang)$$ lang="$$lang$$" xml:lang="$$lang$$"$$endif$$>
3
+<head>
4
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5
+  <meta http-equiv="Content-Style-Type" content="text/css" />
6
+  <meta name="generator" content="pandoc" />
7
+$for(author-meta)$
8
+  <meta name="author" content="$author-meta$" />
9
+$endfor$
10
+$if(date-meta)$
11
+  <meta name="date" content="$date-meta$" />
12
+$endif$
13
+$$if(pagetitle)$$
14
+  <title>$$pagetitle$$ &mdash; $title$</title>
15
+$$else$$
16
+  <title>$title$</title>
17
+$$endif$$
18
+  <style type="text/css">code{white-space: pre;}</style>
19
+$$if(quotes)$$
20
+  <style type="text/css">q { quotes: "“" "”" "‘" "’"; }</style>
21
+$$endif$$
22
+$$if(highlighting-css)$$
23
+  <style type="text/css">
24
+$$highlighting-css$$
25
+  </style>
26
+$$endif$$
27
+$$for(css)$$
28
+  <link rel="stylesheet" href="$$css$$" $$if(html5)$$$$else$$type="text/css" $$endif$$/>
29
+$$endfor$$
30
+$$if(math)$$
31
+  $$math$$
32
+$$endif$$
33
+$$for(header-includes)$$
34
+  $$header-includes$$
35
+$$endfor$$
36
+</head>
37
+<body>
38
+$$for(include-before)$$
39
+$$include-before$$
40
+$$endfor$$
41
+<div class="header">
42
+<ul>
43
+<li><a href="index.html">$title$</a></li>
44
+</ul>
45
+</div>
46
+<div class="columns">
47
+<div class="sidebar">
48
+$body$
49
+$$if(toc)$$
50
+<ul>
51
+<li><a href="#">$$title$$</a>
52
+$$toc$$
53
+</li>
54
+</ul>
55
+$$endif$$
56
+</div>
57
+<div class="body">
58
+$$if(title)$$
59
+<h1 class="title">$$title$$</h1>
60
+$$endif$$
61
+$$body$$
62
+</div>
63
+</div>
64
+<div class="footer">
65
+&copy; Copyright $date$$for(author)$, $author$$endfor$.
66
+Created using <a href="http://johnmacfarlane.net/pandoc/">Pandoc</a>.
67
+</div>
68
+$$for(include-after)$$
69
+$$include-after$$
70
+$$endfor$$
71
+</body>
72
+</html>

+ 83
- 0
doc/reference.mdwn View File

@@ -0,0 +1,83 @@
1
+% Reference
2
+
3
+Unit systems
4
+------------
5
+
6
+`units.read_xml([path])`
7
+
8
+  : Reads a [units database] in XML format and returns a unit system. If the
9
+    path to the database is ommitted, the function reads the path specified
10
+    in the environment variable `UDUNITS2_XML_PATH`; or, if unset, the default
11
+    database.
12
+
13
+    [units database]: http://www.unidata.ucar.edu/software/udunits/udunits-2/udunits2.html#Database
14
+
15
+`system:get_dimensionless_unit_one()`
16
+
17
+  : Returns the unit of dimension 1.
18
+
19
+`system:get_unit_by_name(s)`
20
+
21
+  : Returns the unit that matches the given name in a case-insensitive manner.
22
+
23
+`system:get_unit_by_symbol(s)`
24
+
25
+  : Returns the unit that matches the given symbol in a case-sensitive manner.
26
+
27
+`system:parse(s[, encoding])`
28
+
29
+  : Parses the given unit string and returns the corresponding unit. A second,
30
+    optional argument `encoding` specifies the character encoding of the
31
+    string.
32
+
33
+    `encoding` may be any of the following:
34
+
35
+    * **"ascii"**;
36
+    * **"iso_8859_1"**;
37
+    * **"latin1"** (an alias of **"iso_8859_1"**);
38
+    * **"utf8"** (the default).
39
+
40
+
41
+Units
42
+-----
43
+
44
+`x * unit`
45
+
46
+  : Returns a unit that equals `unit` scaled by `x`.
47
+
48
+`unit * x`
49
+
50
+  : Returns a unit that equals `unit` scaled by `x`.
51
+
52
+`unit1 * unit2`
53
+
54
+  : Returns a unit that equals the product of the two units.
55
+
56
+`x / unit`
57
+
58
+  : Returns a unit that equals the inverse of `unit` scaled by `x`.
59
+
60
+`unit / x`
61
+
62
+  : Returns a unit that equals `unit` scaled by the inverse of `x`.
63
+
64
+`unit1 / unit2`
65
+
66
+  : Returns a unit that equals the quotient of the two units.
67
+
68
+`unit ^ n`
69
+
70
+  : Returns a unit that equals `unit` raised to the power of `n`.
71
+
72
+`unit % x`
73
+
74
+  : Returns a unit that equals `unit` offset by `x`.
75
+
76
+`unit1 == unit2`
77
+
78
+  : Returns **true** if the two units belong to the same unit system and
79
+    are equal; otherwise returns **false**.
80
+
81
+`tostring(unit)`
82
+
83
+  : Returns a string representation of `unit` in ASCII character encoding.

+ 35
- 0
test/.luacov View File

@@ -0,0 +1,35 @@
1
+return {
2
+  -- filename to store stats collected
3
+  statsfile = "luacov.stats.out",
4
+
5
+  -- filename to store report
6
+  reportfile = "luacov.report.out",
7
+
8
+  -- Run reporter on completion? (won't work for ticks)
9
+  runreport = true,
10
+
11
+  -- Delete stats file after reporting?
12
+  deletestats = false,
13
+
14
+  -- Patterns for files to include when reporting
15
+  -- all will be included if nothing is listed
16
+  -- (exclude overrules include, do not include
17
+  -- the .lua extension)
18
+  include = {
19
+    "units%.init$",
20
+    "^%w+$",
21
+  },
22
+
23
+  -- Patterns for files to exclude when reporting
24
+  -- all will be included if nothing is listed
25
+  -- (exclude overrules include, do not include
26
+  -- the .lua extension)
27
+  exclude = {
28
+    "luacov$",
29
+    "luacov%.reporter$",
30
+    "luacov%.defaults$",
31
+    "luacov%.runner$",
32
+    "luacov%.stats$",
33
+    "luacov%.tick$",
34
+  },
35
+}

+ 26
- 0
test/Makefile View File

@@ -0,0 +1,26 @@
1
+#
2
+# Lua Units.
3
+# Copyright © 2013 Peter Colberg.
4
+# For conditions of distribution and use, see copyright notice in LICENSE.
5
+#
6
+
7
+LUA = luajit
8
+
9
+ifdef LUA_PATH
10
+  LUA_PATH := $(CURDIR)/../?.lua;$(CURDIR)/../?/init.lua;$(LUA_PATH)
11
+else
12
+  LUA_PATH := $(CURDIR)/../?.lua;$(CURDIR)/../?/init.lua;;
13
+endif
14
+export LUA_PATH
15
+
16
+TESTS = unit
17
+
18
+all: $(TESTS)
19
+
20
+%: %.lua
21
+	$(LUA) $<
22
+
23
+clean:
24
+	$(RM) *.out
25
+
26
+.PHONY: clean

+ 48
- 0
test/unit.lua View File

@@ -0,0 +1,48 @@
1
+------------------------------------------------------------------------------
2
+-- Test units.
3
+-- Copyright © 2013 Peter Colberg.
4
+-- For conditions of distribution and use, see copyright notice in LICENSE.
5
+------------------------------------------------------------------------------
6
+
7
+pcall(require, "luacov")
8
+
9
+local units = require("units")
10
+
11
+local system = units.read_xml()
12
+
13
+local U = function(s) return system:parse(s) end
14
+
15
+assert(system:get_dimensionless_unit_one() == U"1")
16
+assert(system:get_unit_by_name("celsius") == U"°C")
17
+assert(system:get_unit_by_name("CELSIUS") == U"°C")
18
+assert(system:get_unit_by_symbol("m") == U"m")
19
+assert(not pcall(function() return system:get_unit_by_symbol("M") end))
20
+
21
+do
22
+  local celsius = system:get_unit_by_symbol("°C")
23
+  local fahrenheit = system:get_unit_by_symbol("°F")
24
+  assert(system:parse("5/9 K @ 459.67", "ascii") == fahrenheit)
25
+  assert(system:parse("\176C", "iso_8859_1") == celsius)
26
+  assert(system:parse("\176F", "latin1") == fahrenheit)
27
+  assert(system:parse("°C", "utf8") == celsius)
28
+  assert(system:parse("°F") == fahrenheit)
29
+end
30
+
31
+assert(1000 * U"m" == U"km")
32
+assert(U"m" * 1000 == U"km")
33
+assert(U"m" * U"m" == U"m2")
34
+assert(U"m" / 1000 == U"mm")
35
+assert(1000 / U"m" == U"1000 m-1")
36
+assert(U"m" / U"m" == U"1")
37
+assert(U"m" * U"kg" / U"s" ^ 2 == U"N")
38
+assert(U"K" % 273.15 == U"°C")
39
+
40
+do
41
+  assert(U"kg" == system:parse("kg"))
42
+  local system = units.read_xml()
43
+  assert(U"kg" ~= system:parse("kg"))
44
+end
45
+
46
+assert(tostring(U"2 m") == "2 m")
47
+assert(tostring(U"1e+3 m²") == "1000 m2")
48
+assert(tostring(U"°C") == "K @ 273.15")

+ 91
- 0
units/C.c View File

@@ -0,0 +1,91 @@
1
+/*
2
+ * Lua Units.
3
+ * Copyright © 2013 Peter Colberg.
4
+ * For conditions of distribution and use, see copyright notice in LICENSE.
5
+ */
6
+
7
+#include <stdarg.h>
8
+#define va_list void *
9
+
10
+#include <udunits2.h>
11
+
12
+#include "ffi-cdecl.h"
13
+#include "ffi-cdecl-luajit.h"
14
+
15
+cdecl_const(UT_DEFINITION)
16
+cdecl_const(UT_NAMES)
17
+
18
+cdecl_func(cv_combine)
19
+cdecl_func(cv_convert_double)
20
+cdecl_func(cv_convert_doubles)
21
+cdecl_func(cv_convert_float)
22
+cdecl_func(cv_convert_floats)
23
+cdecl_func(cv_free)
24
+cdecl_func(cv_get_expression)
25
+cdecl_func(cv_get_galilean)
26
+cdecl_func(cv_get_inverse)
27
+cdecl_func(cv_get_log)
28
+cdecl_func(cv_get_offset)
29
+cdecl_func(cv_get_pow)
30
+cdecl_func(cv_get_scale)
31
+cdecl_func(cv_get_trivial)
32
+cdecl_func(ut_accept_visitor)
33
+cdecl_func(ut_add_name_prefix)
34
+cdecl_func(ut_add_symbol_prefix)
35
+cdecl_func(ut_are_convertible)
36
+cdecl_func(ut_clone)
37
+cdecl_func(ut_compare)
38
+cdecl_func(ut_decode_time)
39
+cdecl_func(ut_divide)
40
+cdecl_func(ut_encode_clock)
41
+cdecl_func(ut_encode_date)
42
+cdecl_func(ut_encode_time)
43
+cdecl_func(ut_format)
44
+cdecl_func(ut_free)
45
+cdecl_func(ut_free_system)
46
+cdecl_func(ut_get_converter)
47
+cdecl_func(ut_get_dimensionless_unit_one)
48
+cdecl_func(ut_get_name)
49
+cdecl_func(ut_get_status)
50
+cdecl_func(ut_get_symbol)
51
+cdecl_func(ut_get_system)
52
+cdecl_func(ut_get_unit_by_name)
53
+cdecl_func(ut_get_unit_by_symbol)
54
+cdecl_func(ut_handle_error_message)
55
+cdecl_func(ut_ignore)
56
+cdecl_func(ut_invert)
57
+cdecl_func(ut_is_dimensionless)
58
+cdecl_func(ut_log)
59
+cdecl_func(ut_map_name_to_unit)
60
+cdecl_func(ut_map_symbol_to_unit)
61
+cdecl_func(ut_map_unit_to_name)
62
+cdecl_func(ut_map_unit_to_symbol)
63
+cdecl_func(ut_multiply)
64
+cdecl_func(ut_new_base_unit)
65
+cdecl_func(ut_new_dimensionless_unit)
66
+cdecl_func(ut_new_system)
67
+cdecl_func(ut_offset)
68
+cdecl_func(ut_offset_by_time)
69
+cdecl_func(ut_parse)
70
+cdecl_func(ut_raise)
71
+cdecl_func(ut_read_xml)
72
+cdecl_func(ut_root)
73
+cdecl_func(ut_same_system)
74
+cdecl_func(ut_scale)
75
+cdecl_func(ut_set_error_message_handler)
76
+cdecl_func(ut_set_second)
77
+cdecl_func(ut_set_status)
78
+cdecl_func(ut_trim)
79
+cdecl_func(ut_unmap_name_to_unit)
80
+cdecl_func(ut_unmap_symbol_to_unit)
81
+cdecl_func(ut_unmap_unit_to_name)
82
+cdecl_func(ut_unmap_unit_to_symbol)
83
+cdecl_func(ut_write_to_stderr)
84
+
85
+cdecl_type(cv_converter)
86
+cdecl_type(ut_encoding)
87
+cdecl_type(ut_error_message_handler)
88
+cdecl_type(ut_status)
89
+cdecl_type(ut_system)
90
+cdecl_type(ut_unit)
91
+cdecl_type(ut_visitor)

+ 23
- 0
units/C.lua.in View File

@@ -0,0 +1,23 @@
1
+------------------------------------------------------------------------------
2
+-- Lua Units.
3
+-- Copyright © 2013 Peter Colberg.
4
+-- For conditions of distribution and use, see copyright notice in LICENSE.
5
+------------------------------------------------------------------------------
6
+
7
+local ffi = require("ffi")
8
+
9
+ffi.cdef[[
10
+@CDECL@
11
+]]
12
+
13
+-- If the udunits2 library has been linked to the application, use udunits2
14
+-- symbols from default, global namespace. Otherwise, dynamically load
15
+-- the udunits2 library into its own, non-global C library namespace.
16
+local C
17
+if pcall(function() return ffi.C.ut_get_status end) then
18
+  C = ffi.C
19
+else
20
+  C = ffi.load("@LIBNAME@")
21
+end
22
+
23
+return C

+ 36
- 0
units/Makefile View File

@@ -0,0 +1,36 @@
1
+#
2
+# Lua Units.
3
+# Copyright © 2013 Peter Colberg.
4
+# For conditions of distribution and use, see copyright notice in LICENSE.
5
+#
6
+
7
+CC        = gcc
8
+CPPFLAGS  = -I$(FFI_CDECL_DIR)
9
+CFLAGS    = -std=c99 -Wall -pedantic
10
+GCCLUA    = $(CURDIR)/../../gcc-lua/gcc/gcclua.so
11
+FFI_CDECL = $(FFI_CDECL_DIR)/ffi-cdecl.lua
12
+LIBNAME   = udunits2
13
+
14
+ifndef FFI_CDECL_DIR
15
+  GCC_CDECL_DIR = $(CURDIR)/../../gcc-lua-cdecl
16
+  FFI_CDECL_DIR = $(GCC_CDECL_DIR)/ffi-cdecl
17
+  ifdef LUA_PATH
18
+    LUA_PATH := $(GCC_CDECL_DIR)/?.lua;$(GCC_CDECL_DIR)/?/init.lua;$(LUA_PATH)
19
+  else
20
+    LUA_PATH := $(GCC_CDECL_DIR)/?.lua;$(GCC_CDECL_DIR)/?/init.lua;;
21
+  endif
22
+  export LUA_PATH
23
+endif
24
+
25
+all: C.lua
26
+
27
+%.lua: %.c %.lua.tmp
28
+	$(CC) -S -fplugin=$(GCCLUA) -fplugin-arg-gcclua-script=$(FFI_CDECL) -fplugin-arg-gcclua-input=$*.lua.tmp -fplugin-arg-gcclua-output=$@ $(CPPFLAGS) $(CFLAGS) $<
29
+
30
+%.lua.tmp: %.lua.in
31
+	sed 's#@LIBNAME@#$(LIBNAME)#' $< > $@
32
+
33
+clean:
34
+	$(RM) C.lua
35
+
36
+.PHONY: clean

+ 143
- 0
units/init.lua View File

@@ -0,0 +1,143 @@
1
+------------------------------------------------------------------------------
2
+-- Lua Units.
3
+-- Copyright © 2013 Peter Colberg.
4
+-- For conditions of distribution and use, see copyright notice in LICENSE.
5
+------------------------------------------------------------------------------
6
+
7
+local C   = require("units.C")
8
+local ffi = require("ffi")
9
+
10
+local _M = {}
11
+
12
+-- C types.
13
+local char_n = ffi.typeof("char[?]")
14
+
15
+-- Object types.
16
+local system_id = ffi.typeof("struct { ut_system *id; }")
17
+local unit_id   = ffi.typeof("struct { ut_unit *id; }")
18
+
19
+-- Object methods.
20
+local system = {}
21
+local unit   = {}
22
+
23
+-- Object metamethods.
24
+local system_mt = {__index = system}
25
+local unit_mt   = {__index = unit}
26
+
27
+local errors = {
28
+  [C.UT_SUCCESS]         = "success",
29
+  [C.UT_BAD_ARG]         = "an argument violates the function's contract",
30
+  [C.UT_EXISTS]          = "unit prefix or identifier already exists",
31
+  [C.UT_NO_UNIT]         = "no such unit exists",
32
+  [C.UT_OS]              = "operating-system error",
33
+  [C.UT_NOT_SAME_SYSTEM] = "the units belong to different unit-systems",
34
+  [C.UT_MEANINGLESS]     = "the operation on the unit(s) is meaningless",
35
+  [C.UT_NO_SECOND]       = "the unit-system doesn't have a unit named 'second'",
36
+  [C.UT_VISIT_ERROR]     = "an error occurred while visiting a unit",
37
+  [C.UT_CANT_FORMAT]     = "a unit can't be formatted in the desired manner",
38
+  [C.UT_SYNTAX]          = "string unit representation contains syntax error",
39
+  [C.UT_UNKNOWN]         = "string unit representation contains unknown word",
40
+  [C.UT_OPEN_ARG]        = "can't open argument-specified unit database",
41
+  [C.UT_OPEN_ENV]        = "can't open environment-specified unit database",
42
+  [C.UT_OPEN_DEFAULT]    = "can't open installed default unit database",
43
+  [C.UT_PARSE]           = "error parsing unit specification",
44
+}
45
+
46
+-- Returns status message of the last function call.
47
+function get_status()
48
+  local status = tonumber(C.ut_get_status())
49
+  return assert(errors[status])
50
+end
51
+
52
+-- Do not print error messages to console.
53
+assert(C.ut_set_error_message_handler(C.ut_ignore) ~= nil)
54
+
55
+function _M.read_xml(path)
56
+  local system = C.ut_read_xml(path)
57
+  if system == nil then return error(get_status()) end
58
+  return system_id(system)
59
+end
60
+
61
+function system.get_dimensionless_unit_one(system)
62
+  local unit = C.ut_get_dimensionless_unit_one(system.id)
63
+  if unit == nil then return error(get_status()) end
64
+  return unit_id(unit)
65
+end
66
+
67
+function system.get_unit_by_name(system, s)
68
+  local unit = C.ut_get_unit_by_name(system.id, s)
69
+  if unit == nil then return error(get_status()) end
70
+  return unit_id(unit)
71
+end
72
+
73
+function system.get_unit_by_symbol(system, s)
74
+  local unit = C.ut_get_unit_by_symbol(system.id, s)
75
+  if unit == nil then return error(get_status()) end
76
+  return unit_id(unit)
77
+end
78
+
79
+local encodings = {
80
+  ascii      = C.UT_ASCII,
81
+  iso_8859_1 = C.UT_ISO_8859_1,
82
+  latin1     = C.UT_LATIN1,
83
+  utf8       = C.UT_UTF8,
84
+}
85
+
86
+function system.parse(system, s, encoding)
87
+  if encoding ~= nil then encoding = encodings[encoding] else encoding = C.UT_UTF8 end
88
+  local unit = C.ut_parse(system.id, s, encoding)
89
+  if unit == nil then return error(get_status()) end
90
+  return unit_id(unit)
91
+end
92
+
93
+function unit_mt.__gc(unit)
94
+  return C.ut_free(unit.id)
95
+end
96
+
97
+function unit_mt.__mul(unit1, unit2)
98
+  local unit
99
+  if type(unit1) == "number" then unit1, unit2 = unit2, unit1 end
100
+  if type(unit2) == "number" then unit = C.ut_scale(unit2, unit1.id) else unit = C.ut_multiply(unit1.id, unit2.id) end
101
+  if unit == nil then return error(get_status()) end
102
+  return unit_id(unit)
103
+end
104
+
105
+function unit_mt.__div(unit1, unit2)
106
+  if type(unit1) == "number" then return unit2 ^ -1 * unit1 end
107
+  if type(unit2) == "number" then return unit1 * (1 / unit2) end
108
+  local unit = C.ut_divide(unit1.id, unit2.id)
109
+  if unit == nil then return error(get_status()) end
110
+  return unit_id(unit)
111
+end
112
+
113
+function unit_mt.__pow(unit, n)
114
+  local unit = C.ut_raise(unit.id, n)
115
+  if unit == nil then return error(get_status()) end
116
+  return unit_id(unit)
117
+end
118
+
119
+function unit_mt.__mod(unit, x)
120
+  local unit = C.ut_offset(unit.id, x)
121
+  if unit == nil then return error(get_status()) end
122
+  return unit_id(unit)
123
+end
124
+
125
+function unit_mt.__eq(unit1, unit2)
126
+  if not ffi.istype(unit1, unit2) then return false end
127
+  return C.ut_compare(unit1.id, unit2.id) == 0
128
+end
129
+
130
+do
131
+  local size = 256
132
+  local buf = char_n(size)
133
+  function unit_mt.__tostring(unit)
134
+    local len = C.ut_format(unit.id, buf, size, C.UT_ASCII)
135
+    if len < 0 then return error(get_status()) end
136
+    return ffi.string(buf, len)
137
+  end
138
+end
139
+
140
+ffi.metatype(system_id, system_mt)
141
+ffi.metatype(unit_id, unit_mt)
142
+
143
+return _M

Loading…
Cancel
Save