├── .gitignore ├── Makefile ├── .github └── workflows │ └── ci.yml ├── shelve-0.35.3-1.rockspec ├── CHANGELOG.md ├── test.lua ├── shelve.h ├── anydb.h ├── README.md ├── shelve.c ├── marshal.c └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | .stamp 2 | test.db 3 | *.rock 4 | *.o 5 | *.so 6 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: .stamp 2 | 3 | .stamp: $(wildcard *.c) $(wildcard *.rockspec) 4 | luarocks make --pack-binary-rock 5 | touch $@ 6 | 7 | clean: 8 | $(RM) *.rock *.o *.so test.db .stamp 9 | 10 | test: .stamp 11 | lua test.lua 12 | 13 | .PHONY: test 14 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | build: 13 | strategy: 14 | matrix: 15 | lua: 16 | - "lua 5.1" 17 | - "lua 5.2" 18 | - "lua 5.3" 19 | - "lua 5.4" 20 | - "luajit 2.0" 21 | - "luajit 2.1" 22 | runs-on: ubuntu-22.04 23 | steps: 24 | - name: Checkout 25 | uses: actions/checkout@v3 26 | - name: Dependencies 27 | run: |- 28 | sudo apt install libgdbm-dev 29 | - name: Hererocks 30 | run: |- 31 | pip install hererocks 32 | hererocks env --${{ matrix.lua }} -rlatest 33 | - name: Build 34 | run: |- 35 | source ./env/bin/activate 36 | luarocks make 37 | - name: Test 38 | run: |- 39 | source ./env/bin/activate 40 | lua test.lua 41 | -------------------------------------------------------------------------------- /shelve-0.35.3-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "shelve" 2 | version = "0.35.3-1" 3 | source = { 4 | url = "git://github.com/aperezdc/lua-shelve", 5 | tag = "v0.35.3" 6 | } 7 | description = { 8 | summary = "Serialization and on-disk persistence for Lua values", 9 | detailed = [[ 10 | The shelve module implemets a persistent table-like storage 11 | data structure which can store any Lua data values, which are 12 | marshalled and unmarshalled transparently. Persistence uses 13 | the GDBM or NDBM libraries. 14 | ]], 15 | license = "LGPLv2" 16 | } 17 | dependencies = { 18 | "lua >= 5.1" 19 | } 20 | external_dependencies = { 21 | LIBGDBM = { 22 | header = "gdbm.h" 23 | } 24 | } 25 | build = { 26 | type = "builtin", 27 | modules = { 28 | shelve = { 29 | defines = { 30 | "NDEBUG" 31 | }, 32 | libraries = { 33 | "gdbm" 34 | }, 35 | sources = { 36 | "marshal.c", "shelve.c" 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. This 4 | project adheres to [Semantic Versioning](http://semver.org). 5 | 6 | ## [Unreleased] 7 | 8 | ## [v0.35.3] - 2020-01-14 9 | ### Fixed 10 | - Make it possible to build again with LuaJIT 2.1 11 | 12 | ## [v0.35.2] - 2020-01-14 13 | ### Changed 14 | - The `__tostring` metamethod for a shelve userdata no longer includes the 15 | file name of the shelve in the values it returns. 16 | 17 | ### Fixed 18 | - The module can now be built and used with LuaJIT 2.0 and 2.1. 19 | 20 | ## [v0.35.1] - 2016-04-18 21 | ### Changed 22 | - The `__call` metamethod for a shelve userdata now returns an iterator 23 | function instead of a table with the keys. 24 | 25 | ## [v0.35.0] - 2016-02-03 26 | ### Changed 27 | - Adopted Semantic Versioning. 28 | - This changelog now follows the [Keep A Changelog](http://keepachangelog.com/) 29 | format. 30 | - Source code indentation style now uses spaces, never tabs. 31 | - Travis-CI is now used for continuous integration. 32 | 33 | ## [v0.34] - 2016-02-02 34 | ### Changed 35 | - Made the code buildable again, supporting Lua versions 5.1, 5.2 and 5.3 36 | - Added rockspec for LuaRocks. 37 | 38 | ## v0.33 - 2003-04-23 39 | ### Fixed 40 | - Removed unneeded `xfree(udata)` in the `__gc` metamethod of the shelve type. 41 | This caused occassional segmentation faults. 42 | 43 | [Unreleased]: https://github.com/aperezdc/lua-shelve/compare/v0.35.3...HEAD 44 | [v0.35.3]: https://github.com/aperezdc/lua-shelve/compare/v0.35.2...v0.35.3 45 | [v0.35.2]: https://github.com/aperezdc/lua-shelve/compare/v0.35.1...v0.35.2 46 | [v0.35.1]: https://github.com/aperezdc/lua-shelve/compare/v0.35.0...v0.35.1 47 | [v0.35.0]: https://github.com/aperezdc/lua-shelve/compare/v0.34...v0.35.0 48 | [v0.34]: https://github.com/aperezdc/lua-shelve/compare/v0.33...v0.34 49 | -------------------------------------------------------------------------------- /test.lua: -------------------------------------------------------------------------------- 1 | 2 | local printf 3 | if unpack ~= nil then 4 | printf = function(fmt, ...) 5 | io.stdout:write(string.format(fmt, unpack(arg))) 6 | end 7 | else 8 | printf = function(fmt, ...) 9 | io.stdout:write(string.format(fmt, ...)) 10 | end 11 | end 12 | 13 | package.cpath = "./?.so" 14 | local shelve = assert(require("shelve")) 15 | print("Opening 'db'") 16 | os.remove("test.db") 17 | local db = assert(shelve.open("test.db")) 18 | 19 | local num_keys = 0 20 | for key in db() do num_keys = num_keys + 1 end 21 | assert(num_keys == 0) 22 | 23 | a = "one" 24 | b = "two" 25 | c = "three" 26 | 27 | db.num = 1234567890 -- a number 28 | db.str = "a string" -- a string 29 | db.t1 = {} -- an empty table 30 | db.t2 = { s="S" } -- table with one element 31 | db.t3 = { a,b,c } -- indexed table, multiple elements 32 | 33 | for key in db() do num_keys = num_keys + 1 end 34 | assert(num_keys == 5) 35 | 36 | db.nested = -- nested tables 37 | { 38 | level = a, 39 | nest = { 40 | level = b, 41 | nest = { 42 | level = c, 43 | nest = "nothing" 44 | } 45 | } 46 | } 47 | 48 | printf("Number encoding... ") 49 | assert(type(db.num) == "number") 50 | assert(db.num == 1234567890) 51 | printf("ok\nString encoding... ") 52 | assert(db.str == "a string") 53 | printf("ok\nTable encoding... ") 54 | assert(type(db.t1) == "table") 55 | assert(type(db.t2) == "table") 56 | assert(type(db.t3) == "table") 57 | printf("ok\nData integrity... ") 58 | assert(db.t2.s == "S") 59 | assert(db.t3[1] == a) 60 | assert(db.t3[2] == b) 61 | assert(db.t3[3] == c) 62 | t = db.nested 63 | assert(type(t) == "table") 64 | assert(t.level == a) 65 | assert(type(t.nest) == "table") 66 | assert(t.nest.level == b) 67 | assert(type(t.nest.nest) == "table") 68 | assert(t.nest.nest.level == c) 69 | assert(type(t.nest.nest.nest) == "string") 70 | assert(t.nest.nest.nest == "nothing") 71 | printf("ok\nLarge file storing... ") 72 | 73 | fd, err = io.open("LICENSE", "r") 74 | if (not fd) then 75 | print(err) 76 | os.exit() 77 | end 78 | lgpl_license = fd:read("*a") 79 | fd:close() 80 | 81 | db.lic = lgpl_license 82 | assert(db.lic == lgpl_license) 83 | printf("ok\n... all tests successfully passed ...\n") 84 | -------------------------------------------------------------------------------- /shelve.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Marshaling/Unmarshaling functions, Shelve module exports. 3 | * Copyright (C) 2003-2016 Adrian Perez de Castro 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | 21 | #ifndef __lua_module_shelve__h 22 | #define __lua_module_shelve__h 23 | 24 | #include 25 | 26 | #if (defined(__GNUC__) && __GNUC__ >= 4) || __clang__ 27 | # define LOCAL_SYMBOL __attribute__((visibility("hidden"))) 28 | #else 29 | # define LOCAL_SYMBOL 30 | #endif 31 | 32 | /* 33 | * Lua to byte-array marshaling functions. Representation of 34 | * numbers is machine-dependant. 35 | * 36 | * Format: 37 | * 'n'XXXX Number: XXXX=value, sizeof(lua_Number) 38 | * 's'XXXXS String: XXXX=length, sizeof(size_t), S=contents. 39 | * 'b' Boolean, false. 40 | * 'B' Boolean, true. 41 | * 't'XXXX{} Table: XXXX=number of items, sizeof(size_t). 42 | * Each element: KV. 43 | * KV K: key, either nXXXX or sXXXXS (only in tables). 44 | * V: value, either nXXXX, sXXXXS, b, B or t{}. 45 | * '!' End-of-sequence marker. 46 | * 'T' End-of-table marker. 47 | */ 48 | 49 | #define MARSH_NUMBER 'n' 50 | #define MARSH_STRING 's' 51 | #define MARSH_TRUE 'B' 52 | #define MARSH_FALSE 'b' 53 | #define MARSH_TABLE 't' 54 | #define MARSH_EOT 'T' 55 | #define MARSH_EOS '!' 56 | 57 | LOCAL_SYMBOL int shelve_marshal(lua_State*, char**, int*); 58 | LOCAL_SYMBOL int shelve_unmarshal(lua_State*, const char**); 59 | LOCAL_SYMBOL int shelve_module_marshal(lua_State*); 60 | LOCAL_SYMBOL int shelve_module_unmarshal(lua_State*); 61 | 62 | #endif /* !__lua_module_shelve__h */ 63 | -------------------------------------------------------------------------------- /anydb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Gdbm/Ndbm wrapper header. 3 | * Wrappers are modelled after the Gdbm prototypes. 4 | * 5 | * Copyright (C) 2003-2016 Adrian Perez de Castro 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | #ifndef __anydb__h 23 | #define __anydb__h 24 | 25 | /* Useable DBM backends */ 26 | #define ANYDB_NDBM 1 27 | #define ANYDB_GDBM 2 28 | 29 | /* Handle Autoconf like HAVE_GDBM and HAVE_NDBM, Gdbm used by default */ 30 | #ifndef ANYDB_BACKEND 31 | # if defined(HAVE_GDBM) 32 | # define ANYDB_BACKEND ANYDB_GDBM 33 | # elif defined(HAVE_NDBM) 34 | # define ANYDB_BACKEND ANYDB_NDBM 35 | # else 36 | # define ANYDB_BACKEND ANYDB_GDBM 37 | # endif 38 | #endif 39 | 40 | /* Use rw-rw--- mode by default */ 41 | #ifndef ANYDB_OPEN_MODE 42 | # define ANYDB_OPEN_MODE 0660 43 | #endif 44 | 45 | /* Define wrappers depending on the used backend */ 46 | #if (ANYDB_BACKEND == ANYDB_NDBM) 47 | # include /* Backend header file */ 48 | # include /* O_CREAT and O_RDWR macros */ 49 | # define ANYDB_READ O_RDONLY 50 | # define ANYDB_WRITE (O_CREAT | O_RDWR) 51 | # define ANYDB_INSERT DBM_INSERT 52 | # define ANYDB_REPLACE DBM_REPLACE 53 | typedef DBM* anydb_t; /* Database handle type */ 54 | # define anydb_open(_n,_f) dbm_open(_n, _f, ANYDB_OPEN_MODE) 55 | # define anydb_close dbm_close 56 | # define anydb_store dbm_store 57 | # define anydb_fetch dbm_fetch 58 | # define anydb_delete dbm_delete 59 | # define anydb_firstkey dbm_firstkey 60 | # define anydb_nextkey(_h,_k) dbm_nextkey(_h) 61 | # define anydb_reorganize(_i) ((void)0) 62 | #elif (ANYDB_BACKEND == ANYDB_GDBM) 63 | # include /* Backend header file */ 64 | # define ANYDB_READ GDBM_READER 65 | # define ANYDB_WRITE GDBM_WRCREAT 66 | # define ANYDB_INSERT GDBM_INSERT 67 | # define ANYDB_REPLACE GDBM_REPLACE 68 | typedef GDBM_FILE anydb_t; /* Database handle type */ 69 | # define anydb_open(_n,_f) gdbm_open(_n, 0, _f, ANYDB_OPEN_MODE, NULL) 70 | # define anydb_close gdbm_close 71 | # define anydb_store gdbm_store 72 | # define anydb_fetch gdbm_fetch 73 | # define anydb_delete gdbm_delete 74 | # define anydb_firstkey gdbm_firstkey 75 | # define anydb_nextkey gdbm_nextkey 76 | # define anydb_reorganize gdbm_reorganize 77 | #else 78 | /* No backend defined -> error */ 79 | # error Neither Ndbm or Gdbm configured. 80 | #endif 81 | 82 | #endif /* !__anydb__h */ 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lua Shelve Module 2 | 3 | [![CI Status](https://github.com/aperezdc/lua-shelve/actions/workflows/ci.yml/badge.svg)](https://github.com/aperezdc/lua-shelve/actions/workflows/ci.yml) 4 | 5 | This is a Lua module that uses either GNU Gdbm or the more standard Ndbm 6 | database libraries to store data in files, but this data is saved in 7 | a special way: all standard Lua datatypes may be directly stored and 8 | retrieved in its original form and contents, including Lua tables. A shelf 9 | file is a special kind of userdata that behaves similarly to a Lua table, so 10 | its contents are accessed in a table- like fashion. Quick example: 11 | 12 | ```lua 13 | -- Create data 14 | my_table = { 15 | name = "This is a string within a table", 16 | level= 1, 17 | is_at_level_one = true, 18 | another_table = { 19 | name = "This is a nested table", 20 | level= 2, 21 | is_at_level_one = false 22 | } 23 | } 24 | 25 | -- Open a 'shelve' file 26 | file = shelve.open("data") 27 | 28 | -- This encodes & stores the above table 29 | -- Dotted and bracketed syntax may be used interchangeably 30 | file["my_table"] = my_table 31 | file.title = "File containing a string and a table" 32 | 33 | -- Show contents of the file in (key, value) form 34 | for key in file() do 35 | print("(" .. key .. ", " .. tostring(file[key]) .. ")") 36 | end 37 | ``` 38 | 39 | The name of the module, `shelve`, is taken from the Python's module 40 | with the same name, as both work in a similar way. The nuts & bolts 41 | of the module are coded directly in C, so operation speed is fairly 42 | fast. 43 | 44 | 45 | ## Requirements 46 | 47 | In order to build and use the this Lua module, you will need the following: 48 | 49 | - Working C compiler, GCC recommended. 50 | - GNU DBM (aka Gdbm) or the standard Unix Ndbm. If you have the old Unix DBM 51 | please upgrade to Gdbm or Ndbm. Gdbm is better. 52 | - Lua 5.0 beta or above, including headers and libraries. 53 | - GNU Make (ok, you may also build manually...). I don't know whether other 54 | versions of Make will work. 55 | 56 | If you want to compile the module as a dynamically loadable library 57 | (plugin) you will also need the following: 58 | 59 | - Lua interpreter with `loadlib(`" support. Most modern operating systems 60 | (Linux, MacOS X, Windows, BSD...) can handle this. 61 | 62 | 63 | ## Operation 64 | 65 | To gain access to a data file, you must open it first. The module defines 66 | an `open()` function that receives two parameters: 67 | 68 | ```lua 69 | file_handle = shelve.open(file_name, access_mode) 70 | ``` 71 | 72 | - `file_name` is the path of the file you want to open. 73 | - `access_mode` is a string describing how the file should be accessed. 74 | `"r"` means readonly, and any other string will will be interpreted 75 | as read+write access. If you don't pass the second parameter, 76 | read+write access is assumed. Note that the mode in which a file is 77 | opened is important: a writer needs exclusive access to the file, but 78 | various readers may read it concurrently. When you need only read-access, 79 | please use this option, and you will get better response when several 80 | processes/threads are working with the same data file. 81 | 82 | In order to retain the structure and type information of the data, it must be 83 | encoded with this information included. The result of coding is a stream of 84 | bytes. The `shelve` data files are standard Gdbm/Ndbm files that contain 85 | these encoded bytestreams as data, and the specified identifier as key of 86 | the data, so the following Lua statement: 87 | 88 | ```lua 89 | file["a number"] = 12345 90 | ``` 91 | 92 | Will use the string `a number` as key and the encoded form of the `12345` 93 | numeric value as data in the Gdbm/Ndbm file. 94 | 95 | The opposite action: 96 | 97 | ```lua 98 | num = file["a number"] 99 | ``` 100 | 101 | Will look-up for the `a number` key in the Gdbm/Ndbm file. If the key does 102 | *not* exist, a `nil` value is returned, otherwise the bytestream associated 103 | with the key will be read and decoded in order to return the original Lua 104 | structure. 105 | 106 | To delete a *(key, data)* pair from the file, just assign `nil` to the key. 107 | Example: 108 | 109 | ``` 110 | file = shelve.open("test") 111 | file.number = 12345 -- this assignment defines "number" 112 | file.number = nil -- this assignment deletes "number" 113 | ``` 114 | 115 | Indexing a shelve file with an undefined key will always return `nil`. 116 | Example: 117 | 118 | ``` 119 | file = shelve.open("test") 120 | file.number = 12345 -- this assignment defines "number" 121 | print(file.number) -- prints "12345" 122 | file.number = nil -- this assignment deletes "number" 123 | print(file.number) -- prints "nil" 124 | print(file.undefined) -- prints "nil", again 125 | ``` 126 | 127 | In order to close a shelf, just assign let it be garbage-collected When Gdbm 128 | is used as backend and the file was open in read+write mode, it will be 129 | reorganized on close. 130 | 131 | 132 | ## Extras 133 | 134 | The module also defines two standalone functions that perform the 135 | encoding/decoding of data: 136 | 137 | ```lua 138 | encoded = shelve.marshal(value) 139 | ``` 140 | 141 | Encodes `value` and returns the encoded bytestream as a Lua string. 142 | 143 | ```lua 144 | value = shelve.unmarshal(encoded): 145 | ``` 146 | 147 | Takes an `encoded` Lua string and returns the decoded Lua value. 148 | 149 | The relantionship between these two functions is that one is the 150 | inverse of the other, so: 151 | 152 | ```lua 153 | data1 == shelve.unmarshal(shelve.marshal(data1)) -- true 154 | data2 == shelve.marshal(shelve.unmarshal(data2)) -- true 155 | ``` 156 | 157 | You may use these functions to manually encode and decode data. 158 | Note that `shelve.marshal()` adds a special mark to the end of an 159 | encoded bytestream: decoding the concatenation of two encoded 160 | values will only return the first one. 161 | 162 | 163 | ## Known Limitations 164 | 165 | - Data files are NOT portable across: 166 | - Platforms with different endianness and word sizes. 167 | - Different builds of the shelve module when one uses GDBM and the other 168 | uses NDBM (this is because they don't use the same internal file format). 169 | - Functions, userdata and light userdata **cannot** be encoded and stored in 170 | a shelf. If you try to encode one of these you will get an error. In 171 | particular, it is not possible to store/marshal regular or `shelve` file 172 | handles. 173 | - Trying to encode a table that has references to itself produces an infinite 174 | loop recursion, thus a hang or a stack overflow will occur. 175 | -------------------------------------------------------------------------------- /shelve.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Lua interface of the 'shelve' module. 3 | * Copyright (C) 2003-2016 Adrian Perez de Castro 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include "shelve.h" 28 | #include "anydb.h" 29 | 30 | /* 31 | * LuaJIT defines LUA_LJDIR in , which is always included 32 | * indirectly, so when the symbol is available we know that 33 | * is also around and can be included to check LUAJIT_VERSION_NUM below. 34 | */ 35 | #ifdef LUA_LJDIR 36 | # include 37 | #endif 38 | 39 | #if defined(LUAJIT_VERSION_NUM) && LUAJIT_VERSION_NUM >= 20100 40 | # define SHELVE_HAVE_LUAL_SETMETATABLE 41 | #elif LUA_VERSION_NUM >= 502 42 | # define SHELVE_HAVE_LUAL_SETMETATABLE 43 | #else 44 | # undef SHELVE_HAVE_LUAL_SETMETATABLE 45 | #endif 46 | 47 | static const char SHELVE_META[] = "shelve-file-meta"; 48 | static const char SHELVE_ITER_META[] = "shelve-file-iter-meta"; 49 | 50 | #ifndef LUALIB_API 51 | # define LUALIB_API API 52 | #endif 53 | 54 | #ifndef SHELVE_HAVE_LUAL_SETMETATABLE 55 | static void 56 | luaL_setmetatable(lua_State *L, const char *name) 57 | { 58 | lua_pushstring(L, name); 59 | lua_gettable(L, LUA_REGISTRYINDEX); 60 | lua_setmetatable(L, -2); 61 | lua_remove(L, -2); 62 | } 63 | #endif 64 | 65 | 66 | struct Shelve { 67 | anydb_t db; 68 | int ro; 69 | }; 70 | 71 | struct Iterator { 72 | anydb_t db; 73 | datum k; 74 | }; 75 | 76 | 77 | static int 78 | iterator_next(lua_State *L) 79 | { 80 | struct Iterator *i = lua_touserdata(L, lua_upvalueindex(1)); 81 | if (i->k.dptr) { 82 | datum k; 83 | lua_pushlstring(L, i->k.dptr, (size_t) i->k.dsize); 84 | k = i->k; 85 | i->k = anydb_nextkey(i->db, k); 86 | free(k.dptr); 87 | return 1; 88 | } 89 | return 0; 90 | } 91 | 92 | static int 93 | iterator_gc(lua_State *L) 94 | { 95 | struct Iterator *i = lua_touserdata(L, -1); 96 | free(i->k.dptr); 97 | i->k.dptr = NULL; 98 | return 0; 99 | } 100 | 101 | static luaL_Reg iterator_meta[] = { 102 | { "__gc", iterator_gc }, 103 | { NULL, NULL }, 104 | }; 105 | 106 | 107 | static int 108 | shelve_index(lua_State *L) 109 | { 110 | datum d, k; 111 | size_t slen_aux; 112 | struct Shelve *self = luaL_checkudata(L, 1, SHELVE_META); 113 | 114 | k.dptr = (char*) lua_tolstring(L, 2, &slen_aux); 115 | k.dsize = (int) slen_aux; 116 | d = anydb_fetch(self->db, k); 117 | 118 | if (d.dptr) { 119 | const char *datap = d.dptr; 120 | if (!shelve_unmarshal(L, &datap)) { 121 | luaL_error(L, "bad format in encoded data"); 122 | } 123 | free(d.dptr); 124 | } else { 125 | lua_pushnil(L); 126 | } 127 | return 1; 128 | } 129 | 130 | static int 131 | shelve_newindex(lua_State *L) 132 | { 133 | datum k, d = { NULL, 0 }; 134 | size_t slen_aux; 135 | struct Shelve *self = luaL_checkudata(L, 1, SHELVE_META); 136 | 137 | k.dptr = (char*) lua_tolstring(L, 2, &slen_aux); 138 | k.dsize = (int) slen_aux; 139 | 140 | if (self->ro) { 141 | return luaL_error(L, "cannot modify read-only shelf datafile"); 142 | } 143 | 144 | if (lua_isnil(L, 3)) { 145 | /* Remove key in database. */ 146 | anydb_delete(self->db, k); 147 | return 0; 148 | } 149 | 150 | if (!shelve_marshal(L, &d.dptr, &d.dsize)) { 151 | return luaL_error(L, "cannot encode data"); 152 | } 153 | 154 | if (anydb_store(self->db, k, d, ANYDB_REPLACE) != 0) { 155 | free(d.dptr); 156 | return luaL_error(L, "cannot update item in data file"); 157 | } 158 | free(d.dptr); 159 | 160 | return 0; 161 | } 162 | 163 | static int 164 | shelve_call(lua_State *L) 165 | { 166 | struct Shelve *self = luaL_checkudata(L, -1, SHELVE_META); 167 | 168 | struct Iterator *i = lua_newuserdata(L, sizeof(struct Iterator)); 169 | i->k = anydb_firstkey(self->db); 170 | i->db = self->db; 171 | luaL_setmetatable(L, SHELVE_ITER_META); 172 | 173 | lua_pushcclosure(L, iterator_next, 1); 174 | return 1; 175 | } 176 | 177 | static int 178 | shelve_gc(lua_State *L) 179 | { 180 | struct Shelve *self = luaL_checkudata(L, 1, SHELVE_META); 181 | if (!self->ro) { 182 | anydb_reorganize(self->db); 183 | } 184 | anydb_close(self->db); 185 | return 0; 186 | } 187 | 188 | static int 189 | shelve_tostring(lua_State *L) 190 | { 191 | struct Shelve *self = luaL_checkudata(L, 1, SHELVE_META); 192 | lua_pushfstring(L, "shelve (%p, %s)", self->db, self->ro ? "ro" : "rw"); 193 | return 1; 194 | } 195 | 196 | static luaL_Reg shelve_meta[] = { 197 | { "__index", shelve_index }, 198 | { "__newindex", shelve_newindex }, 199 | { "__call", shelve_call }, 200 | { "__gc", shelve_gc }, 201 | { "__tostring", shelve_tostring }, 202 | { NULL, NULL }, 203 | }; 204 | 205 | 206 | static int 207 | shelve_module_open(lua_State *L) 208 | { 209 | int flags = ANYDB_WRITE; 210 | struct Shelve *self = NULL; 211 | const char *rwmode = NULL; 212 | anydb_t db; 213 | int n = lua_gettop(L); 214 | 215 | /* Check arguments. */ 216 | if ((n != 1) && (n != 2)) { 217 | luaL_error(L, "function takes one or two arguments"); 218 | } 219 | 220 | /* Check & get second argument (if needed). */ 221 | if (n == 2) { 222 | rwmode = luaL_checkstring(L, 2); 223 | flags = (*rwmode == 'r') ? ANYDB_READ : ANYDB_WRITE; 224 | } 225 | 226 | /* Open the DB and remove filename from the stack. */ 227 | if (!(db = anydb_open(luaL_checkstring(L, 1), flags))) { 228 | lua_pushnil(L); 229 | lua_pushstring(L, strerror(errno)); 230 | return 2; 231 | } 232 | 233 | self = lua_newuserdata(L, sizeof(struct Shelve)); 234 | self->ro = (flags == ANYDB_READ); 235 | self->db = db; 236 | 237 | /* Associate metatable with userdata. */ 238 | luaL_setmetatable(L, SHELVE_META); 239 | 240 | return 1; 241 | } 242 | 243 | static luaL_Reg shelve_module[] = { 244 | { "open", shelve_module_open }, 245 | { "marshal", shelve_module_marshal }, 246 | { "unmarshal", shelve_module_unmarshal }, 247 | { NULL, NULL }, 248 | }; 249 | 250 | 251 | LUALIB_API int 252 | luaopen_shelve(lua_State *L) 253 | { 254 | assert(L); 255 | 256 | /* Shelve file metatable */ 257 | luaL_newmetatable(L, SHELVE_META); 258 | #if LUA_VERSION_NUM < 502 259 | luaL_register(L, NULL, shelve_meta); 260 | #else 261 | luaL_setfuncs(L, shelve_meta, 0); 262 | #endif 263 | 264 | /* Shelve file iterator metatable */ 265 | luaL_newmetatable(L, SHELVE_ITER_META); 266 | #if LUA_VERSION_NUM < 502 267 | luaL_register(L, NULL, iterator_meta); 268 | #else 269 | luaL_setfuncs(L, iterator_meta, 0); 270 | #endif 271 | 272 | /* Module */ 273 | #if LUA_VERSION_NUM < 502 274 | luaL_register(L, "shelve", shelve_module); 275 | #else 276 | luaL_newlib(L, shelve_module); 277 | #endif 278 | 279 | return 1; 280 | } 281 | -------------------------------------------------------------------------------- /marshal.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * (Un)Marshaling of Lua datatypes. 4 | * Copyright (C) 2003-2016 Adrian Perez de Castro 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "shelve.h" 27 | 28 | 29 | #define GROW(_dp, _szvar, _sz) \ 30 | _szvar += (_sz); \ 31 | _dp = ((_dp) ? realloc(_dp, _szvar * sizeof(char)) \ 32 | : malloc(_szvar * sizeof(char))) 33 | 34 | #define STOR(_dp, _szvar, _what, _sz) \ 35 | { GROW(_dp, _szvar, _sz); \ 36 | memcpy(&(_dp)[(_szvar) - (_sz)], _what, _sz); } 37 | 38 | 39 | static int marshal_table(lua_State*, char**, int*); 40 | static int unmarshal_table(lua_State*, const char**); 41 | 42 | 43 | int 44 | shelve_unmarshal(lua_State *L, const char **datap) 45 | { 46 | size_t ssz; 47 | const char *data = *datap; 48 | 49 | assert(L); 50 | assert(data); 51 | 52 | switch (*(data++)) { 53 | case MARSH_FALSE: /* 'false' boolean value */ 54 | lua_pushboolean(L, 0); 55 | break; 56 | case MARSH_TRUE: /* 'true' boolean value */ 57 | lua_pushboolean(L, 1); 58 | break; 59 | case MARSH_NUMBER: /* numeric value */ 60 | lua_pushnumber(L, (lua_Number) (*((double*) data)) ); 61 | data += sizeof(double); 62 | break; 63 | case MARSH_STRING: /* string value */ 64 | ssz = *((size_t*) data); 65 | data += sizeof(size_t); 66 | lua_pushlstring(L, data, ssz); 67 | data += ssz; 68 | break; 69 | case MARSH_TABLE: /* table */ 70 | if (!unmarshal_table(L, &data)) return 0; 71 | break; 72 | default: 73 | return 0; 74 | } 75 | 76 | if (*(data++) != MARSH_EOS) return 0; 77 | 78 | *datap = data; 79 | return 1; 80 | } 81 | 82 | 83 | int 84 | unmarshal_table(lua_State *L, const char **datap) 85 | { 86 | const char *data = *datap; 87 | 88 | assert(L); 89 | assert(data); 90 | 91 | lua_newtable(L); 92 | /* 93 | * stack: tbl 94 | * index: -1 95 | */ 96 | 97 | for (;;) { 98 | switch (*data) { 99 | case MARSH_NUMBER: /* valid key (number) */ 100 | case MARSH_STRING: /* valid key (string) */ 101 | if (!shelve_unmarshal(L, &data) || 102 | !shelve_unmarshal(L, &data)) return 0; 103 | /* 104 | * stack: data key tbl 105 | * index: -1 -2 -3 106 | */ 107 | lua_rawset(L, -3); 108 | break; 109 | case MARSH_EOT: /* end of table */ 110 | data++; 111 | /* 112 | * I know using 'goto' is not structured programming, but 113 | * I use it to avoid checking "*data" twice. Without 114 | * 'goto' the code would look like the following: 115 | * 116 | * while (*data != MARSH_EOS) { 117 | * switch (*data) { 118 | * ... some code ... 119 | * } 120 | * } 121 | */ 122 | goto loop_end; 123 | default: /* not number, not string: invalid key */ 124 | return 0; 125 | } 126 | } 127 | loop_end: 128 | 129 | *datap = data; 130 | return 1; 131 | } 132 | 133 | 134 | int 135 | shelve_marshal(lua_State *L, char **data, int *bytes) 136 | { 137 | size_t slen; 138 | size_t slen_aux; 139 | char ch; 140 | 141 | assert(L); 142 | assert(data); 143 | assert(bytes); 144 | assert(lua_gettop(L) > 0); 145 | 146 | switch (lua_type(L, -1)) { 147 | case LUA_TNUMBER: /* Encode a number. */ 148 | slen = 1 + sizeof(double); 149 | { 150 | char __d[slen]; 151 | __d[0] = MARSH_NUMBER; 152 | *((double*)(&__d[1])) = (double) lua_tonumber(L, -1); 153 | STOR(*data, *bytes, __d, slen); 154 | } 155 | break; 156 | case LUA_TBOOLEAN: /* Encode a boolean value. */ 157 | ch = (lua_toboolean(L, -1)) ? MARSH_TRUE : MARSH_FALSE; 158 | STOR(*data, *bytes, &ch, 1); 159 | break; 160 | case LUA_TSTRING: /* Encode a string value. */ 161 | slen = 1 + sizeof(size_t); 162 | { 163 | char __d[slen]; 164 | const char *lstr = lua_tolstring (L, -1, &slen_aux); 165 | __d[0] = MARSH_STRING; 166 | *((size_t*)(&__d[1])) = slen_aux; 167 | STOR(*data, *bytes, __d, slen); 168 | STOR(*data, *bytes, lstr, slen_aux); 169 | } 170 | break; 171 | case LUA_TTABLE: /* Encode a table. */ 172 | if (!marshal_table(L, data, bytes)) return 0; 173 | case LUA_TNIL: /* Just skip the 'nil' value. */ 174 | break; 175 | case LUA_TFUNCTION: 176 | case LUA_TUSERDATA: 177 | case LUA_TLIGHTUSERDATA: 178 | default: /* Cannot handle userdatas or functions. */ 179 | return 0; 180 | } 181 | 182 | ch = MARSH_EOS; 183 | STOR(*data, *bytes, &ch, 1); 184 | 185 | return 1; 186 | } 187 | 188 | 189 | int 190 | marshal_table(lua_State *L, char **data, int *bytes) 191 | { 192 | char ch = MARSH_TABLE; 193 | 194 | assert(L); 195 | assert(data); 196 | assert(bytes); 197 | assert(lua_type(L, -1) == LUA_TTABLE); 198 | 199 | STOR(*data, *bytes, &ch, 1); 200 | 201 | lua_pushnil(L); 202 | while (lua_next(L, -2)) { 203 | assert(lua_type(L, -3) == LUA_TTABLE); 204 | /* 205 | * - "key" is at index -2 and "value" at index -1 206 | * - "key" must be encoded first, so move it to the top 207 | * lua_insert() moves "value" down to -2 and shifts "key" up to -1 208 | * stack: key val tbl 209 | * index: -1 -2 -3 210 | */ 211 | lua_insert(L, -2); 212 | if (!shelve_marshal(L, data, bytes)) return 0; /* encode "key" */ 213 | assert(lua_type(L, -3) == LUA_TTABLE); 214 | /* 215 | * Again, lua_insert() moves "key" down to -2 and shifted "value" up to -1. 216 | * stack: val key tbl 217 | * index: -1 -2 -3 218 | */ 219 | lua_insert(L, -2); 220 | if (!shelve_marshal(L, data, bytes)) return 0; /* encode "value" */ 221 | assert(lua_type(L, -3) == LUA_TTABLE); 222 | /* 223 | * Pop "value", "key" remains in order to call lua_next() properly. 224 | * stack: key tbl 225 | * index: -1 -2 226 | */ 227 | lua_pop(L, 1); 228 | assert(lua_type(L, -2) == LUA_TTABLE); 229 | } 230 | 231 | assert(lua_type(L, -1) == LUA_TTABLE); 232 | 233 | /* Insert MARSH_EOS */ 234 | ch = MARSH_EOT; 235 | STOR(*data, *bytes, &ch, 1); 236 | 237 | return 1; 238 | } 239 | 240 | 241 | int 242 | shelve_module_marshal(lua_State *L) 243 | { 244 | char *data = NULL; 245 | int sz = 0; 246 | 247 | assert(L); 248 | 249 | if (shelve_marshal(L, &data, &sz)) { 250 | lua_pushlstring(L, data, (size_t) sz); 251 | return 1; 252 | } 253 | 254 | lua_pushnil(L); 255 | lua_pushstring(L, "Cannot encode data"); 256 | return 2; 257 | } 258 | 259 | 260 | int 261 | shelve_module_unmarshal(lua_State *L) 262 | { 263 | const char *data = luaL_checkstring(L, 1); 264 | if (shelve_unmarshal(L, &data)) { 265 | return 1; 266 | } 267 | 268 | return luaL_error(L, "bad format in encoded data"); 269 | } 270 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | GNU LESSER GENERAL PUBLIC LICENSE 3 | Version 2.1, February 1999 4 | 5 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 6 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 7 | Everyone is permitted to copy and distribute verbatim copies 8 | of this license document, but changing it is not allowed. 9 | 10 | [This is the first released version of the Lesser GPL. It also counts 11 | as the successor of the GNU Library Public License, version 2, hence 12 | the version number 2.1.] 13 | 14 | Preamble 15 | 16 | The licenses for most software are designed to take away your 17 | freedom to share and change it. By contrast, the GNU General Public 18 | Licenses are intended to guarantee your freedom to share and change 19 | free software--to make sure the software is free for all its users. 20 | 21 | This license, the Lesser General Public License, applies to some 22 | specially designated software packages--typically libraries--of the 23 | Free Software Foundation and other authors who decide to use it. You 24 | can use it too, but we suggest you first think carefully about whether 25 | this license or the ordinary General Public License is the better 26 | strategy to use in any particular case, based on the explanations 27 | below. 28 | 29 | When we speak of free software, we are referring to freedom of use, 30 | not price. Our General Public Licenses are designed to make sure that 31 | you have the freedom to distribute copies of free software (and charge 32 | for this service if you wish); that you receive source code or can get 33 | it if you want it; that you can change the software and use pieces of 34 | it in new free programs; and that you are informed that you can do 35 | these things. 36 | 37 | To protect your rights, we need to make restrictions that forbid 38 | distributors to deny you these rights or to ask you to surrender these 39 | rights. These restrictions translate to certain responsibilities for 40 | you if you distribute copies of the library or if you modify it. 41 | 42 | For example, if you distribute copies of the library, whether gratis 43 | or for a fee, you must give the recipients all the rights that we gave 44 | you. You must make sure that they, too, receive or can get the source 45 | code. If you link other code with the library, you must provide 46 | complete object files to the recipients, so that they can relink them 47 | with the library after making changes to the library and recompiling 48 | it. And you must show them these terms so they know their rights. 49 | 50 | We protect your rights with a two-step method: (1) we copyright the 51 | library, and (2) we offer you this license, which gives you legal 52 | permission to copy, distribute and/or modify the library. 53 | 54 | To protect each distributor, we want to make it very clear that 55 | there is no warranty for the free library. Also, if the library is 56 | modified by someone else and passed on, the recipients should know 57 | that what they have is not the original version, so that the original 58 | author's reputation will not be affected by problems that might be 59 | introduced by others. 60 | ^L 61 | Finally, software patents pose a constant threat to the existence of 62 | any free program. We wish to make sure that a company cannot 63 | effectively restrict the users of a free program by obtaining a 64 | restrictive license from a patent holder. Therefore, we insist that 65 | any patent license obtained for a version of the library must be 66 | consistent with the full freedom of use specified in this license. 67 | 68 | Most GNU software, including some libraries, is covered by the 69 | ordinary GNU General Public License. This license, the GNU Lesser 70 | General Public License, applies to certain designated libraries, and 71 | is quite different from the ordinary General Public License. We use 72 | this license for certain libraries in order to permit linking those 73 | libraries into non-free programs. 74 | 75 | When a program is linked with a library, whether statically or using 76 | a shared library, the combination of the two is legally speaking a 77 | combined work, a derivative of the original library. The ordinary 78 | General Public License therefore permits such linking only if the 79 | entire combination fits its criteria of freedom. The Lesser General 80 | Public License permits more lax criteria for linking other code with 81 | the library. 82 | 83 | We call this license the "Lesser" General Public License because it 84 | does Less to protect the user's freedom than the ordinary General 85 | Public License. It also provides other free software developers Less 86 | of an advantage over competing non-free programs. These disadvantages 87 | are the reason we use the ordinary General Public License for many 88 | libraries. However, the Lesser license provides advantages in certain 89 | special circumstances. 90 | 91 | For example, on rare occasions, there may be a special need to 92 | encourage the widest possible use of a certain library, so that it 93 | becomes 94 | a de-facto standard. To achieve this, non-free programs must be 95 | allowed to use the library. A more frequent case is that a free 96 | library does the same job as widely used non-free libraries. In this 97 | case, there is little to gain by limiting the free library to free 98 | software only, so we use the Lesser General Public License. 99 | 100 | In other cases, permission to use a particular library in non-free 101 | programs enables a greater number of people to use a large body of 102 | free software. For example, permission to use the GNU C Library in 103 | non-free programs enables many more people to use the whole GNU 104 | operating system, as well as its variant, the GNU/Linux operating 105 | system. 106 | 107 | Although the Lesser General Public License is Less protective of the 108 | users' freedom, it does ensure that the user of a program that is 109 | linked with the Library has the freedom and the wherewithal to run 110 | that program using a modified version of the Library. 111 | 112 | The precise terms and conditions for copying, distribution and 113 | modification follow. Pay close attention to the difference between a 114 | "work based on the library" and a "work that uses the library". The 115 | former contains code derived from the library, whereas the latter must 116 | be combined with the library in order to run. 117 | ^L 118 | GNU LESSER GENERAL PUBLIC LICENSE 119 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 120 | 121 | 0. This License Agreement applies to any software library or other 122 | program which contains a notice placed by the copyright holder or 123 | other authorized party saying it may be distributed under the terms of 124 | this Lesser General Public License (also called "this License"). 125 | Each licensee is addressed as "you". 126 | 127 | A "library" means a collection of software functions and/or data 128 | prepared so as to be conveniently linked with application programs 129 | (which use some of those functions and data) to form executables. 130 | 131 | The "Library", below, refers to any such software library or work 132 | which has been distributed under these terms. A "work based on the 133 | Library" means either the Library or any derivative work under 134 | copyright law: that is to say, a work containing the Library or a 135 | portion of it, either verbatim or with modifications and/or translated 136 | straightforwardly into another language. (Hereinafter, translation is 137 | included without limitation in the term "modification".) 138 | 139 | "Source code" for a work means the preferred form of the work for 140 | making modifications to it. For a library, complete source code means 141 | all the source code for all modules it contains, plus any associated 142 | interface definition files, plus the scripts used to control 143 | compilation 144 | and installation of the library. 145 | 146 | Activities other than copying, distribution and modification are not 147 | covered by this License; they are outside its scope. The act of 148 | running a program using the Library is not restricted, and output from 149 | such a program is covered only if its contents constitute a work based 150 | on the Library (independent of the use of the Library in a tool for 151 | writing it). Whether that is true depends on what the Library does 152 | and what the program that uses the Library does. 153 | 154 | 1. You may copy and distribute verbatim copies of the Library's 155 | complete source code as you receive it, in any medium, provided that 156 | you conspicuously and appropriately publish on each copy an 157 | appropriate copyright notice and disclaimer of warranty; keep intact 158 | all the notices that refer to this License and to the absence of any 159 | warranty; and distribute a copy of this License along with the 160 | Library. 161 | 162 | You may charge a fee for the physical act of transferring a copy, 163 | and you may at your option offer warranty protection in exchange for a 164 | fee. 165 | 166 | 2. You may modify your copy or copies of the Library or any portion 167 | of it, thus forming a work based on the Library, and copy and 168 | distribute such modifications or work under the terms of Section 1 169 | above, provided that you also meet all of these conditions: 170 | 171 | a) The modified work must itself be a software library. 172 | 173 | b) You must cause the files modified to carry prominent notices 174 | stating that you changed the files and the date of any change. 175 | 176 | c) You must cause the whole of the work to be licensed at no 177 | charge to all third parties under the terms of this License. 178 | 179 | d) If a facility in the modified Library refers to a function or a 180 | table of data to be supplied by an application program that uses 181 | the facility, other than as an argument passed when the facility 182 | is invoked, then you must make a good faith effort to ensure that, 183 | in the event an application does not supply such function or 184 | table, the facility still operates, and performs whatever part of 185 | its purpose remains meaningful. 186 | 187 | (For example, a function in a library to compute square roots has 188 | a purpose that is entirely well-defined independent of the 189 | application. Therefore, Subsection 2d requires that any 190 | application-supplied function or table used by this function must 191 | be optional: if the application does not supply it, the square 192 | root function must still compute square roots.) 193 | 194 | These requirements apply to the modified work as a whole. If 195 | identifiable sections of that work are not derived from the Library, 196 | and can be reasonably considered independent and separate works in 197 | themselves, then this License, and its terms, do not apply to those 198 | sections when you distribute them as separate works. But when you 199 | distribute the same sections as part of a whole which is a work based 200 | on the Library, the distribution of the whole must be on the terms of 201 | this License, whose permissions for other licensees extend to the 202 | entire whole, and thus to each and every part regardless of who wrote 203 | it. 204 | 205 | Thus, it is not the intent of this section to claim rights or contest 206 | your rights to work written entirely by you; rather, the intent is to 207 | exercise the right to control the distribution of derivative or 208 | collective works based on the Library. 209 | 210 | In addition, mere aggregation of another work not based on the Library 211 | with the Library (or with a work based on the Library) on a volume of 212 | a storage or distribution medium does not bring the other work under 213 | the scope of this License. 214 | 215 | 3. You may opt to apply the terms of the ordinary GNU General Public 216 | License instead of this License to a given copy of the Library. To do 217 | this, you must alter all the notices that refer to this License, so 218 | that they refer to the ordinary GNU General Public License, version 2, 219 | instead of to this License. (If a newer version than version 2 of the 220 | ordinary GNU General Public License has appeared, then you can specify 221 | that version instead if you wish.) Do not make any other change in 222 | these notices. 223 | ^L 224 | Once this change is made in a given copy, it is irreversible for 225 | that copy, so the ordinary GNU General Public License applies to all 226 | subsequent copies and derivative works made from that copy. 227 | 228 | This option is useful when you wish to copy part of the code of 229 | the Library into a program that is not a library. 230 | 231 | 4. You may copy and distribute the Library (or a portion or 232 | derivative of it, under Section 2) in object code or executable form 233 | under the terms of Sections 1 and 2 above provided that you accompany 234 | it with the complete corresponding machine-readable source code, which 235 | must be distributed under the terms of Sections 1 and 2 above on a 236 | medium customarily used for software interchange. 237 | 238 | If distribution of object code is made by offering access to copy 239 | from a designated place, then offering equivalent access to copy the 240 | source code from the same place satisfies the requirement to 241 | distribute the source code, even though third parties are not 242 | compelled to copy the source along with the object code. 243 | 244 | 5. A program that contains no derivative of any portion of the 245 | Library, but is designed to work with the Library by being compiled or 246 | linked with it, is called a "work that uses the Library". Such a 247 | work, in isolation, is not a derivative work of the Library, and 248 | therefore falls outside the scope of this License. 249 | 250 | However, linking a "work that uses the Library" with the Library 251 | creates an executable that is a derivative of the Library (because it 252 | contains portions of the Library), rather than a "work that uses the 253 | library". The executable is therefore covered by this License. 254 | Section 6 states terms for distribution of such executables. 255 | 256 | When a "work that uses the Library" uses material from a header file 257 | that is part of the Library, the object code for the work may be a 258 | derivative work of the Library even though the source code is not. 259 | Whether this is true is especially significant if the work can be 260 | linked without the Library, or if the work is itself a library. The 261 | threshold for this to be true is not precisely defined by law. 262 | 263 | If such an object file uses only numerical parameters, data 264 | structure layouts and accessors, and small macros and small inline 265 | functions (ten lines or less in length), then the use of the object 266 | file is unrestricted, regardless of whether it is legally a derivative 267 | work. (Executables containing this object code plus portions of the 268 | Library will still fall under Section 6.) 269 | 270 | Otherwise, if the work is a derivative of the Library, you may 271 | distribute the object code for the work under the terms of Section 6. 272 | Any executables containing that work also fall under Section 6, 273 | whether or not they are linked directly with the Library itself. 274 | ^L 275 | 6. As an exception to the Sections above, you may also combine or 276 | link a "work that uses the Library" with the Library to produce a 277 | work containing portions of the Library, and distribute that work 278 | under terms of your choice, provided that the terms permit 279 | modification of the work for the customer's own use and reverse 280 | engineering for debugging such modifications. 281 | 282 | You must give prominent notice with each copy of the work that the 283 | Library is used in it and that the Library and its use are covered by 284 | this License. You must supply a copy of this License. If the work 285 | during execution displays copyright notices, you must include the 286 | copyright notice for the Library among them, as well as a reference 287 | directing the user to the copy of this License. Also, you must do one 288 | of these things: 289 | 290 | a) Accompany the work with the complete corresponding 291 | machine-readable source code for the Library including whatever 292 | changes were used in the work (which must be distributed under 293 | Sections 1 and 2 above); and, if the work is an executable linked 294 | with the Library, with the complete machine-readable "work that 295 | uses the Library", as object code and/or source code, so that the 296 | user can modify the Library and then relink to produce a modified 297 | executable containing the modified Library. (It is understood 298 | that the user who changes the contents of definitions files in the 299 | Library will not necessarily be able to recompile the application 300 | to use the modified definitions.) 301 | 302 | b) Use a suitable shared library mechanism for linking with the 303 | Library. A suitable mechanism is one that (1) uses at run time a 304 | copy of the library already present on the user's computer system, 305 | rather than copying library functions into the executable, and (2) 306 | will operate properly with a modified version of the library, if 307 | the user installs one, as long as the modified version is 308 | interface-compatible with the version that the work was made with. 309 | 310 | c) Accompany the work with a written offer, valid for at 311 | least three years, to give the same user the materials 312 | specified in Subsection 6a, above, for a charge no more 313 | than the cost of performing this distribution. 314 | 315 | d) If distribution of the work is made by offering access to copy 316 | from a designated place, offer equivalent access to copy the above 317 | specified materials from the same place. 318 | 319 | e) Verify that the user has already received a copy of these 320 | materials or that you have already sent this user a copy. 321 | 322 | For an executable, the required form of the "work that uses the 323 | Library" must include any data and utility programs needed for 324 | reproducing the executable from it. However, as a special exception, 325 | the materials to be distributed need not include anything that is 326 | normally distributed (in either source or binary form) with the major 327 | components (compiler, kernel, and so on) of the operating system on 328 | which the executable runs, unless that component itself accompanies 329 | the executable. 330 | 331 | It may happen that this requirement contradicts the license 332 | restrictions of other proprietary libraries that do not normally 333 | accompany the operating system. Such a contradiction means you cannot 334 | use both them and the Library together in an executable that you 335 | distribute. 336 | ^L 337 | 7. You may place library facilities that are a work based on the 338 | Library side-by-side in a single library together with other library 339 | facilities not covered by this License, and distribute such a combined 340 | library, provided that the separate distribution of the work based on 341 | the Library and of the other library facilities is otherwise 342 | permitted, and provided that you do these two things: 343 | 344 | a) Accompany the combined library with a copy of the same work 345 | based on the Library, uncombined with any other library 346 | facilities. This must be distributed under the terms of the 347 | Sections above. 348 | 349 | b) Give prominent notice with the combined library of the fact 350 | that part of it is a work based on the Library, and explaining 351 | where to find the accompanying uncombined form of the same work. 352 | 353 | 8. You may not copy, modify, sublicense, link with, or distribute 354 | the Library except as expressly provided under this License. Any 355 | attempt otherwise to copy, modify, sublicense, link with, or 356 | distribute the Library is void, and will automatically terminate your 357 | rights under this License. However, parties who have received copies, 358 | or rights, from you under this License will not have their licenses 359 | terminated so long as such parties remain in full compliance. 360 | 361 | 9. You are not required to accept this License, since you have not 362 | signed it. However, nothing else grants you permission to modify or 363 | distribute the Library or its derivative works. These actions are 364 | prohibited by law if you do not accept this License. Therefore, by 365 | modifying or distributing the Library (or any work based on the 366 | Library), you indicate your acceptance of this License to do so, and 367 | all its terms and conditions for copying, distributing or modifying 368 | the Library or works based on it. 369 | 370 | 10. Each time you redistribute the Library (or any work based on the 371 | Library), the recipient automatically receives a license from the 372 | original licensor to copy, distribute, link with or modify the Library 373 | subject to these terms and conditions. You may not impose any further 374 | restrictions on the recipients' exercise of the rights granted herein. 375 | You are not responsible for enforcing compliance by third parties with 376 | this License. 377 | ^L 378 | 11. If, as a consequence of a court judgment or allegation of patent 379 | infringement or for any other reason (not limited to patent issues), 380 | conditions are imposed on you (whether by court order, agreement or 381 | otherwise) that contradict the conditions of this License, they do not 382 | excuse you from the conditions of this License. If you cannot 383 | distribute so as to satisfy simultaneously your obligations under this 384 | License and any other pertinent obligations, then as a consequence you 385 | may not distribute the Library at all. For example, if a patent 386 | license would not permit royalty-free redistribution of the Library by 387 | all those who receive copies directly or indirectly through you, then 388 | the only way you could satisfy both it and this License would be to 389 | refrain entirely from distribution of the Library. 390 | 391 | If any portion of this section is held invalid or unenforceable under 392 | any particular circumstance, the balance of the section is intended to 393 | apply, and the section as a whole is intended to apply in other 394 | circumstances. 395 | 396 | It is not the purpose of this section to induce you to infringe any 397 | patents or other property right claims or to contest validity of any 398 | such claims; this section has the sole purpose of protecting the 399 | integrity of the free software distribution system which is 400 | implemented by public license practices. Many people have made 401 | generous contributions to the wide range of software distributed 402 | through that system in reliance on consistent application of that 403 | system; it is up to the author/donor to decide if he or she is willing 404 | to distribute software through any other system and a licensee cannot 405 | impose that choice. 406 | 407 | This section is intended to make thoroughly clear what is believed to 408 | be a consequence of the rest of this License. 409 | 410 | 12. If the distribution and/or use of the Library is restricted in 411 | certain countries either by patents or by copyrighted interfaces, the 412 | original copyright holder who places the Library under this License 413 | may add an explicit geographical distribution limitation excluding those 414 | countries, so that distribution is permitted only in or among 415 | countries not thus excluded. In such case, this License incorporates 416 | the limitation as if written in the body of this License. 417 | 418 | 13. The Free Software Foundation may publish revised and/or new 419 | versions of the Lesser General Public License from time to time. 420 | Such new versions will be similar in spirit to the present version, 421 | but may differ in detail to address new problems or concerns. 422 | 423 | Each version is given a distinguishing version number. If the Library 424 | specifies a version number of this License which applies to it and 425 | "any later version", you have the option of following the terms and 426 | conditions either of that version or of any later version published by 427 | the Free Software Foundation. If the Library does not specify a 428 | license version number, you may choose any version ever published by 429 | the Free Software Foundation. 430 | ^L 431 | 14. If you wish to incorporate parts of the Library into other free 432 | programs whose distribution conditions are incompatible with these, 433 | write to the author to ask for permission. For software which is 434 | copyrighted by the Free Software Foundation, write to the Free 435 | Software Foundation; we sometimes make exceptions for this. Our 436 | decision will be guided by the two goals of preserving the free status 437 | of all derivatives of our free software and of promoting the sharing 438 | and reuse of software generally. 439 | 440 | NO WARRANTY 441 | 442 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 443 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 444 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 445 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 446 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 447 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 448 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 449 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 450 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 451 | 452 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 453 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 454 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 455 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 456 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 457 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 458 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 459 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 460 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 461 | DAMAGES. 462 | 463 | END OF TERMS AND CONDITIONS 464 | ^L 465 | How to Apply These Terms to Your New Libraries 466 | 467 | If you develop a new library, and you want it to be of the greatest 468 | possible use to the public, we recommend making it free software that 469 | everyone can redistribute and change. You can do so by permitting 470 | redistribution under these terms (or, alternatively, under the terms 471 | of the ordinary General Public License). 472 | 473 | To apply these terms, attach the following notices to the library. 474 | It is safest to attach them to the start of each source file to most 475 | effectively convey the exclusion of warranty; and each file should 476 | have at least the "copyright" line and a pointer to where the full 477 | notice is found. 478 | 479 | 480 | 482 | Copyright (C) 483 | 484 | This library is free software; you can redistribute it and/or 485 | modify it under the terms of the GNU Lesser General Public 486 | License as published by the Free Software Foundation; either 487 | version 2 of the License, or (at your option) any later version. 488 | 489 | This library is distributed in the hope that it will be useful, 490 | but WITHOUT ANY WARRANTY; without even the implied warranty of 491 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 492 | Lesser General Public License for more details. 493 | 494 | You should have received a copy of the GNU Lesser General Public 495 | License along with this library; if not, write to the Free Software 496 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 497 | 498 | Also add information on how to contact you by electronic and paper 499 | mail. 500 | 501 | You should also get your employer (if you work as a programmer) or 502 | your 503 | school, if any, to sign a "copyright disclaimer" for the library, if 504 | necessary. Here is a sample; alter the names: 505 | 506 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 507 | library `Frob' (a library for tweaking knobs) written by James 508 | Random Hacker. 509 | 510 | , 1 April 1990 511 | Ty Coon, President of Vice 512 | 513 | That's all there is to it! 514 | 515 | 516 | --------------------------------------------------------------------------------