├── .gitignore ├── LICENSE ├── README.md ├── autoload ├── .project_tags.config.vim ├── project_tags.vim └── project_tags_tags_file.vim ├── plugin ├── .project_tags.config.vim └── project_tags.vim ├── static test data ├── Collections-C │ ├── .gitignore │ ├── .travis.yml │ ├── AUTHORS │ ├── CONTRIBUTING.md │ ├── COPYING │ ├── ChangeLog │ ├── INSTALL │ ├── Makefile.am │ ├── NEWS │ ├── README │ ├── README.md │ ├── TODO │ ├── autogen.sh │ ├── configure.ac │ ├── install-sh │ ├── src │ │ ├── Makefile.am │ │ ├── array.c │ │ ├── array.h │ │ ├── common.c │ │ ├── common.h │ │ ├── deque.c │ │ ├── deque.h │ │ ├── hashset.c │ │ ├── hashset.h │ │ ├── hashtable.c │ │ ├── hashtable.h │ │ ├── list.c │ │ ├── list.h │ │ ├── queue.c │ │ ├── queue.h │ │ ├── slist.c │ │ ├── slist.h │ │ ├── stack.c │ │ ├── stack.h │ │ ├── treeset.c │ │ ├── treeset.h │ │ ├── treetable.c │ │ └── treetable.h │ └── test │ │ ├── Makefile.am │ │ ├── array_test.c │ │ ├── deque_test.c │ │ ├── hashset_test.c │ │ ├── hashtable_test.c │ │ ├── list_test.c │ │ ├── queue_test.c │ │ ├── slist_test.c │ │ ├── stack_test.c │ │ ├── test.c │ │ ├── test.h │ │ ├── treeset_test.c │ │ └── treetable_test.c ├── another_class.php ├── exclude_dir_project.vim ├── fake tag files │ └── not empty │ │ └── .phptags ├── include_dir_project.vim └── supported_file.php └── tests ├── when_no_project_file_exists_and_saving_php_file.vim ├── when_no_project_file_exists_and_saving_txt_file.vim ├── when_project_file_exists_and_2_php_files_exist_and_saving_php_file.vim ├── when_project_file_exists_and_saving_php_file.vim ├── when_project_file_exists_and_saving_txt_file.vim ├── when_specifying_exclude_dir.vim ├── when_specifying_include_dir_and_saving_code_from_the_project_dir.vim ├── when_working_with_c_project_and_project_file_exists_and_saving_c_file.vim └── when_working_with_c_project_and_project_file_exists_and_saving_h_file.vim /.gitignore: -------------------------------------------------------------------------------- 1 | vimtags 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vim-project-tags [![Join the chat at https://gitter.im/still-dreaming-1/vim-project-tags](https://badges.gitter.im/still-dreaming-1/vim-project-tags.svg)](https://gitter.im/still-dreaming-1/vim-project-tags?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 2 | An improved tags experience based on the concept of projects. 3 | 4 | **Warning** 5 | 6 | 7 | This is an abandoned project. I personally no longer have any use for tags, and I no longer wish to maintain this project. Insted of tags, I recommend using a language server or something like that which understands your code more deeply and uses the context of where you are performing an action to improve the accuracy of the result. For me tags continued to have too many false positives for my purposes even after refining this plugin, and my final conclusion is that tags themselves are a poor fit for what I was trying to use them for (mostly code definition lookup). 8 | 9 | When I say I no longer whish to maintain this plugin, what I mean is, this plugin relies on my vim-eliv library, and I no longer wish to update the master branch of this plugin to be compatible with the latest code in the master branch of vim-elhiv. Theoretically, you should be able to compare the date of the last tagged release of this plugin, and use a commit from the vim-elhiv master branch just before or after that. If someone requests my help in an issue, I will update these instructions to be more helpful. 10 | 11 | If you feel this lack of continued support for this project will affect you negatively, please file an issue. I may be willing to update this plugin to have no external dependencies such that all you ever need to do is use the latest commit from the master branch. This would mean I don't need to update anything to maintain it other than possibly address issues or fix bugs as needed. This would also make it easier to install as you would only need to add it with your plugin manager. 12 | 13 | 14 | **Context** 15 | 16 | This will search for your project root and save separate tag files per programming language for your source code. This plugin creates tag files automatically when you save code files. If you save a .js file, it only creates tags for other .js files in the project, and saves them in their own jstags file. If you save a .php file, it generates tags in a separate phptags file. When you are editing a file, and try to do a code lookup using tags, it will only search one tags file matching the language of the file you are editing, based on file extension. The point of all this is to avoid false positives and keep the tag matches to a minimum. 17 | 18 | **Purpose** 19 | 20 | This allows code lookup and code completion that uses tags to behave more intelligently, closer to how these features would work in a smart IDE. 21 | 22 | `CTRL-]` In Vim, this normally jumps to the definition of the keyword under the cursor relying on tags generated by ctags. This plugin helps you tune and generate your tags so this jump to feature will work better. 23 | 24 | In Vim and Noevim there are features and plugins that provide word/code completion. It is possible to configure your completion to draw from tags. This plugin helps you tune and generate your tags so code completion will work better. You should consult the documention of your favorite completion plugin or feature to set it up to draw from tags. 25 | 26 | **Languages** 27 | 28 | Out of the box, this only automatically generates tags for JavaScript, PHP, and VimL/Vimscript. But you can easily use this plugin with other ctags compatible languages just by specifying file extensions you want to work with. Just call the `project_tags#add_language()` function in your config and pass it a string with the file extension of the language you want to create tags for. Alternatively, you can also pass in a list of file extentions to add support for multiple languages at once. This only works for languages that rely on a single file extension. In other words, it won't work with c because it is split between .c and .h files. Here is an example that adds support for python: 29 | 30 | `call project_tags#add_language('py')` 31 | 32 | Here is an example that adds support for both python and Lua: 33 | 34 | `call project_tags#add_language(['py', 'lua'])` 35 | 36 | You don't need to worry about whether you are adding support for an already supported language. If you call that function with a duplicate file extension, it will just be ignored. This means that if you prefer, you can just call that function for each file extension you want to create tags for without worrying about whether or not the plugin already has built in support for that language. 37 | 38 | You can also provide a custom executable name or full path to to your ctags, but you don't need to. Example: 39 | 40 | `let g:project_tags_ctags_path= 'myctags'` 41 | 42 | **Installation** 43 | 44 | Install it the normal way you install Vim plugins. This also depends on the [vim-elhiv](https://github.com/still-dreaming-1/vim-elhiv/tree/master) plugin, so you will have to install that as well. You need to create a file named ".project_tags.config.vim" and place it in the project root directory of code projects you wish to use this plugin with. 45 | 46 | **Versions** 47 | 48 | Use the latest commit on the master branch, that is the most stable commit. Do not use the latest tag as there may be new commits on master that keep it compatible with the master branch of the elhiv dependency. I only merge the develop branch into master after doing a release or making changes to keep the master branch compatible with the master branch of the elhiv dependency. The master branch works correctly with the latest master branch commit in the vim-elhiv library plugin. Unless you want to contribute code or help me debug, I don't recommend using the develop branch. If you do use the develop branch, realize it is designed to be used with the develop branch of the vim-elhiv library plugin. I haven't yet figured out a good way to tie specific tagged version releases to a specific tagged version of vim-elhiv. If you want to use an older tagged version you will have to compare the commit date and time to that of the commits to vim-elhiv and try it with the vim-elhiv commit just before the vim-project-tags tag/release. If that doesn't work sometimes I find a bug in vim-elhiv and quickly fix it so it may work better with the following vim-elhiv commit. I use automated tests to keep the latest version / master commit stable, so I really recommend just using that. 49 | 50 | **Configuration** 51 | 52 | You need to create a file named ".project_tags.config.vim" and place it in the project root directory of code projects you wish to use this plugin with. Be careful what you place in this file, as it will be sourced and ran as VimL code inside your Vim. The generated tags files will appear inside the same directory as your project configuration file. 53 | 54 | Exclude directory option: 55 | 56 | Inside the project configuration file, you have the option of excluding directories that you don't want to create tags from. Be careful what you place in this file, as it will be sourced and ran as VimL code inside your Vim. Here is an example of using the exclude directory option: 57 | `let g:project_tags_exclude= ['mobile', 'generated_code']` 58 | If you place that line inside your project configuration file, your tags files will not contain tag data from source files inside any subdirectories named "mobile" or "generated_code". The excluded directories will be treated as relative paths from the project file. This may be a useful feature if you frequently find yourself matching false positives when trying to do a code lookup based on tags and the false positives are all inside a specific directory. The exclude and include options can be helpful when used together on the same project. 59 | 60 | Include directory option: 61 | 62 | Inside the project configuration file, you have the option of including extra directories that you want to create tags from. Normally you don't need to use this as tags will be generated for code in your project, but you can use this to generate tags from files in a different location. Be careful what you place in this file, as it will be sourced and ran as VimL code inside your Vim. Here is an example of using the exclude directory option: 63 | `let g:project_tags_include= ['../../some library directory']` 64 | If you place that line inside your project configuration file, your tags files will also contain tag data from source files inside that directory relative to your project configuration file. This is useful if you use a library from a different location. It is also useful when you are using the exclude option, but still want to generate tags from the rest of the project inside the directory being excluded. 65 | 66 | Multiple file types in one tags file: 67 | 68 | Even though the main point of this plugin is to separate file extensions into separate tags files, sometimes you actually want some in the same file. This might be the case if you are working with C code. You may want tags from your .c file and your .h files to exist in the same tags file. In that case there are advantages and disadvantages to keeping them separate or combining them. Combining them should make code completion via tag files more useful if you write your definition in a .h file first and your implemenation in a .c file later. However, it may make jump to work worse if you are trying to jump to the implementation in you .c files and it takes you to the defininition in a .h file. You also might be working with sloppy code where multiple languages exist in the same source file, so this may be another reason to combine multiple file extension types into a single tags file. Here is how you would add C support and combine .c and .h tags: 69 | 70 | `call project_tags#add_language('ctags', ['c', 'h'])` 71 | 72 | Notice you also have to specify the tags filename as the first parmeter. You can call it whatever you want, which brings me to the next option. 73 | 74 | Custom tags file names: 75 | 76 | You can create custom filenames for you tags files. Let's say you are adding python support, your tags files don't need to be called pytags: 77 | 78 | `call project_tags#add_language('nopythontagshere', 'py')` 79 | 80 | Notice how in that case you can keep 'py' as a string, it doesn't need to be in a list if you are just passing one file extension. 81 | -------------------------------------------------------------------------------- /autoload/.project_tags.config.vim: -------------------------------------------------------------------------------- 1 | let g:project_tags_include= ['../plugin'] 2 | -------------------------------------------------------------------------------- /autoload/project_tags.vim: -------------------------------------------------------------------------------- 1 | function! project_tags#generate_tags(...) 2 | call l#log('starting project_tags#generate_tags') 3 | let tags_filename= a:1 4 | let file_extension_list_len= a:0 - 1 5 | let file_extension_list= [] 6 | let i= 0 7 | while i < file_extension_list_len 8 | let a_i= i + 2 9 | let add_string= 'call add(file_extension_list, a:'.a_i.')' 10 | execute add_string 11 | let i= i + 1 12 | endwhile 13 | let project_root_dir= project_tags#find_project_root(L_current_buffer().dir()) 14 | if project_root_dir == L_null() 15 | call l#log('No project root found. Not generating tags') 16 | return 17 | endif 18 | let tags_filepath= project_root_dir.path.'/'.tags_filename 19 | let rm_out= system('rm -f "'.tags_filepath.'"') 20 | let project_config= project_tags#get_immediate_project_file(project_root_dir) 21 | let g:project_tags_exclude= [] 22 | let g:project_tags_include= [] 23 | call l#log('after create project variables before the project file is sourced') 24 | call project_config.source() 25 | let tags_file= project_tags_tags_file#new(project_root_dir, tags_filename, file_extension_list) 26 | if exists('g:project_tags_ctags_path') 27 | let tags_file.ctags_path= g:project_tags_ctags_path 28 | endif 29 | call l#log('before regenerate tags') 30 | call tags_file.regenerate(g:project_tags_exclude, g:project_tags_include) 31 | call l#log('after regenerate tags') 32 | endfunction 33 | 34 | " The simplest way to use this functin is just pass in a file extension as a string (without the .). In that case the name of the tags file is chosen for you. It will be the file 35 | " extensionwith 'tags' added to the end (jstags, phptags, etc). If you pass in 2 parameters, the first is the name of the tags file for the file generated for the file etensions passed 36 | " in the second parameter. The second parameter would then be either a list of file extensions or a single file extension as a string. See project_tags.vim for examples. 37 | function! project_tags#add_language(...) 38 | call l#log('project_tags autoload add_language() start') 39 | if a:0 == 2 40 | let tags_filename= a:1 41 | if type(a:2) == l_type#string() 42 | let file_extension_list= [a:2] 43 | else 44 | let file_extension_list= a:2 45 | endif 46 | endif 47 | if a:0 == 1 48 | let file_extension= a:1 49 | let tags_filename= file_extension.'tags' 50 | let file_extension_list= [file_extension] 51 | endif 52 | 53 | augroup mapping_group 54 | call l#log('project-tags: setting up tag generation for '.tags_filename.' file') 55 | for extension in file_extension_list 56 | let autocmd_string= 'autocmd BufRead *.'.extension.' setlocal tags=./'.tags_filename.';' 57 | call l#log('project_tags: BufRead autocmd: '.autocmd_string) 58 | execute autocmd_string 59 | let autocmd_string= 'autocmd bufwritepost *.'.extension." silent call project_tags#generate_tags('".tags_filename."'" 60 | for file_extension in file_extension_list 61 | let autocmd_string= autocmd_string.", '".file_extension."'" 62 | endfor 63 | let autocmd_string= autocmd_string.')' 64 | call l#log('project_tags: bufwritepost autocmd: '.autocmd_string) 65 | execute autocmd_string 66 | endfor 67 | augroup END 68 | 69 | call l#log('project_tags autoload add_language() end') 70 | endfunction 71 | 72 | function! project_tags#add_built_in_language_support() 73 | call project_tags#add_language('js') 74 | call project_tags#add_language('vim') 75 | call project_tags#add_language('php') 76 | endfunction 77 | 78 | function! project_tags#remove_all_languages() 79 | augroup mapping_group 80 | " removes all autocmd in group 81 | autocmd! 82 | augroup END 83 | endfunction 84 | 85 | function! project_tags#find_project_root(dir) 86 | let proj_conf_file= project_tags#get_immediate_project_file(a:dir) 87 | if proj_conf_file != L_null() 88 | return a:dir 89 | endif 90 | let parent_dir= a:dir.parent() 91 | if parent_dir == L_null() 92 | return L_null() 93 | endif 94 | return project_tags#find_project_root(parent_dir) 95 | endfunction 96 | 97 | function! project_tags#get_immediate_project_file(dir) 98 | let proj_conf_file= a:dir.get_contained_file('.project_tags.config.vim') 99 | if proj_conf_file.readable() 100 | return proj_conf_file 101 | endif 102 | return L_null() 103 | endfunction! 104 | -------------------------------------------------------------------------------- /autoload/project_tags_tags_file.vim: -------------------------------------------------------------------------------- 1 | function! project_tags_tags_file#new(...) 2 | let dir= a:1 3 | let tags_filename= a:2 4 | let file_extension_list= a:3 5 | let tags_file= {} 6 | let tags_file.for_extension_ls= file_extension_list 7 | let tags_file.dir= L_dir(dir.path) 8 | let tags_file.path= dir.get_contained_file(tags_filename).path 9 | let tags_file.ctags_path= 'ctags' 10 | 11 | function! tags_file.regenerate_empty() 12 | let file= L_file(self.path) 13 | if self.readable() && self.size() > 0 14 | call file.delete() 15 | endif 16 | call file.create() 17 | endfunction 18 | 19 | function! tags_file.regenerate(exclude_dir_name_list, include_dir_name_list) 20 | call self.regenerate_empty() 21 | let grep_exclude_str= '' 22 | for exclude_dir_name in a:exclude_dir_name_list 23 | let path= self.dir.get_contained_dir(exclude_dir_name).path 24 | let grep_exclude_str= grep_exclude_str." -ve '^".path."'" 25 | endfor 26 | if len(grep_exclude_str) > 0 27 | let grep_exclude_str= 'grep'.grep_exclude_str.' | ' 28 | endif 29 | let starting_command= 'find '.shellescape(self.dir.path) 30 | for include_dir_name in a:include_dir_name_list 31 | " code to convert list of relative directory names into a list of absolute paths 32 | let include_dir_path= self.dir.get_relative_dir(include_dir_name).path 33 | let starting_command= starting_command.' '.shellescape(include_dir_path) 34 | endfor 35 | for extension in self.for_extension_ls 36 | let extension_search_str= L_s(shellescape(extension)).remove_start().remove_end().str 37 | let extension_search_str= "'*.".extension_search_str."'" 38 | let command= starting_command.' -type f -name '.extension_search_str 39 | \ .' | '.grep_exclude_str.'xargs -d '."'\n' ".self.ctags_path.' --append=yes -f '.shellescape(self.path) 40 | call L_shell().run(command) 41 | endfor 42 | endfunction 43 | 44 | function! tags_file.readable() 45 | return L_file(self.path).readable() 46 | endfunction 47 | 48 | function! tags_file.writable() 49 | return L_file(self.path).writable() 50 | endfunction 51 | 52 | function! tags_file.size() 53 | return L_file(self.path).size() 54 | endfunction 55 | 56 | return tags_file 57 | endfunction 58 | -------------------------------------------------------------------------------- /plugin/.project_tags.config.vim: -------------------------------------------------------------------------------- 1 | let g:project_tags_include= ['../autoload'] 2 | -------------------------------------------------------------------------------- /plugin/project_tags.vim: -------------------------------------------------------------------------------- 1 | call project_tags#add_built_in_language_support() 2 | let s:current_script_path= expand('') 3 | let g:project_tags_dir_path= L_dir(s:current_script_path).parent().parent().path 4 | -------------------------------------------------------------------------------- /static test data/Collections-C/.gitignore: -------------------------------------------------------------------------------- 1 | src/docconf 2 | .project 3 | .cproject 4 | Debug 5 | m4 6 | html 7 | latex 8 | .settings 9 | config 10 | config.bak 11 | *~ 12 | *.o 13 | src/.libs 14 | src/.deps 15 | *.in 16 | configure 17 | depcomp 18 | *.lo 19 | Makefile 20 | aclocal.m4 21 | autom4te.cache/ 22 | compile 23 | config.guess 24 | config.h 25 | config.log 26 | config.status 27 | config.sub 28 | libtool 29 | missing 30 | src/Makefile 31 | src/libcollectc.la 32 | stamp-h1 33 | ltmain.sh 34 | test/*.Po 35 | test/*.log 36 | test/*.trs 37 | test/.deps/* 38 | src/.* 39 | test-driver 40 | 41 | test/treetable_test 42 | 43 | test/treeset_test 44 | 45 | test/stack_test 46 | 47 | test/slist_test 48 | 49 | test/queue_test 50 | 51 | test/list_test 52 | 53 | test/hashtable_test 54 | 55 | test/hashset_test 56 | 57 | test/array_test 58 | 59 | test/deque_test 60 | -------------------------------------------------------------------------------- /static test data/Collections-C/.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | compiler: gcc 3 | script: ./autogen.sh && ./configure && make check 4 | -------------------------------------------------------------------------------- /static test data/Collections-C/AUTHORS: -------------------------------------------------------------------------------- 1 | Srđan Panić 2 | -------------------------------------------------------------------------------- /static test data/Collections-C/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 2 | # Contributing 3 | 4 | To get started, fork the repo to your account and then clone your fork: 5 | ```bash 6 | git clone https://github.com/yourusername/Collections-C.git 7 | ``` 8 | Now you can start working on the project. 9 | 10 | * if you're planing to work on some major new feature, you might want to open an issue first so that it can discuss it. 11 | * If you are writing code, you should follow the code [fomatting style](https://en.wikipedia.org/wiki/Indent_style#K.26R_style). 12 | * Major changes should go into the development branch. 13 | 14 | 15 | 16 | After you're done with your work, you should make sure that the tests are passing with: 17 | ```bash 18 | make check 19 | ``` 20 | Commit your work and push it to your fork. 21 | 22 | You can then open a [pull request](https://help.github.com/articles/using-pull-requests/) from your fork to the upstream repository. After the pull request is made, we will comment / review it and might also suggest some changes. After all that is done, the pull request is merged. 23 | 24 | 25 | ## Finding something to work on 26 | There is always something to work on, be it fixing bugs, writing documentation or adding cool new features. You can start by looking through the [issues](https://github.com/srdja/Collections-C/issues) to find something intereseting. 27 | If you have a cool new idea, or you've found a bug and there is no issue for it, go ahead and open a [new issue](https://github.com/srdja/Collections-C/issues/new) for it. 28 | 29 | If you're just starting out, look for issues with a [low-hanging fruit](https://github.com/srdja/Collections-C/issues?q=is%3Aissue+is%3Aopen+label%3A%22low-hanging+fruit%22) tag. These issues should be fairly easy to fix, and they are also a good starting point for contributing. 30 | -------------------------------------------------------------------------------- /static test data/Collections-C/COPYING: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. -------------------------------------------------------------------------------- /static test data/Collections-C/ChangeLog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/still-dreaming-1/vim-project-tags/562732df2256b52304a15405eb5a566bf2df773a/static test data/Collections-C/ChangeLog -------------------------------------------------------------------------------- /static test data/Collections-C/INSTALL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/still-dreaming-1/vim-project-tags/562732df2256b52304a15405eb5a566bf2df773a/static test data/Collections-C/INSTALL -------------------------------------------------------------------------------- /static test data/Collections-C/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = src test 2 | ACLOCAL_AMFLAGS = -I m4 3 | -------------------------------------------------------------------------------- /static test data/Collections-C/NEWS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/still-dreaming-1/vim-project-tags/562732df2256b52304a15405eb5a566bf2df773a/static test data/Collections-C/NEWS -------------------------------------------------------------------------------- /static test data/Collections-C/README: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/still-dreaming-1/vim-project-tags/562732df2256b52304a15405eb5a566bf2df773a/static test data/Collections-C/README -------------------------------------------------------------------------------- /static test data/Collections-C/README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/srdja/Collections-C.svg?branch=master)](https://travis-ci.org/srdja/Collections-C) 2 | 3 | Collections-C 4 | ============= 5 | 6 | A library of generic data structures including a list, array, hashtable, deque etc.. 7 | 8 | ## Examples 9 | Check the [documentation page](https://srdja.github.io/Collections-C/) for mode detailed examples. (This is still in progress). 10 | The source of the documentation can be found [here](https://github.com/srdja/cc-doc-slate). 11 | 12 | HashTable: 13 | ```c 14 | 15 | // Crate a new table 16 | HashTable *table 17 | if (hashtable_new(&table) != CC_OK) { 18 | // something went wrong 19 | ... 20 | } 21 | 22 | // Add key-value pair 23 | if (hashtable_add(table, "some_key", "some_value") != CC_OK) { 24 | // something went wrong 25 | ... 26 | } 27 | 28 | // Retrieve a value associated with a key 29 | char *value; 30 | if (hashtable_get(table, "some_key", (void*) &value) == CC_OK) 31 | printf("%s", value); 32 | 33 | // Remove a key 34 | hashtable_remove(table, "foo", NULL); 35 | 36 | hashtable_destroy(table); 37 | ``` 38 | Array (dynamic array): 39 | ```c 40 | // Create a new array 41 | Array *ar; 42 | if (array_new(&ar) != CC_OK) { 43 | // something went wrong 44 | ... 45 | } 46 | 47 | // Add an element 48 | enum cc_stat status = array_add(ar, "foo"); 49 | if (status == CC_OK) { 50 | ... 51 | } else if (status == CC_ERR_ALLOC) { 52 | ... 53 | } else { 54 | ... 55 | } 56 | 57 | // Retrieve a value 58 | char *foo; 59 | array_get_at(ar, 0, (void*) &foo); 60 | 61 | // Remove a value 62 | char *removed; 63 | array_remove_at(ar, 0, (void*) &removed); 64 | 65 | array_destroy(ar); 66 | ``` 67 | ## Installation 68 | 69 | ####Dependencies 70 | - gcc 71 | - autoconf 72 | - automake 73 | - libtool 74 | - m4 75 | 76 | These packages can usually be installed through your distributions package manager. 77 | 78 | Building on windows requires [MinGW](http://mingw.org) which provides all the tools needed to build the project. 79 | 80 | #### Building the project 81 | In the project directory, run the following commands: `./autogen.sh` then run `./configure`. If autogen complains that it couldn't find a directory named "m4", run: `mkdir m4` and then `./autogen.sh`. 82 | 83 | - note: Running configure with a prefix like: `./configure --prefix=/some/custom/path` will cause `make install` to install the library to that directory instead of the default one. 84 | 85 | At this point we should be able to build the project by running: 86 | ``` 87 | make 88 | ``` 89 | By default `make` builds a shared library. To build a static library, run make with "static" flag on: `make CFLAGS=-static`. 90 | - note: When building for the 64 bit architecture, "ARCH_64" can be explicitly set like so: `make CFLAGS=-DARCH_64`. This will increase the maximum container capacity to ~2^64. Otherwise the maximum capacity defaults to ~2^32 elements regardless of the target architecture. 91 | 92 | Installing the library: 93 | ``` 94 | make install 95 | ``` 96 | 97 | The tests can be run by: 98 | ``` 99 | make check 100 | ``` 101 | #### Compiling and linking a simple program 102 | - hello.c 103 | ```c 104 | #include 105 | #include 106 | 107 | int main(int argc, char **argv) { 108 | Array *ar; 109 | array_new(&ar); 110 | array_add(ar, "Hello World!\n"); 111 | 112 | char *str; 113 | array_get_at(ar, 0, (void*) &str); 114 | printf("%s", str); 115 | 116 | return 0; 117 | } 118 | ``` 119 | We can now build and statically link the library to our program: 120 | ``` 121 | gcc hello.c -I/path/to/library/include/ -static -L/path/to/library/lib/ -lcollectc -o hello 122 | ``` 123 | 124 | ## Contributors 125 | 126 | All contributions are welcome. 127 | 128 | See [CONTRIBUTING.md](https://github.com/srdja/Collections-C/blob/master/CONTRIBUTING.md) for details. 129 | -------------------------------------------------------------------------------- /static test data/Collections-C/TODO: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static test data/Collections-C/autogen.sh: -------------------------------------------------------------------------------- 1 | autoreconf --force --install 2 | -------------------------------------------------------------------------------- /static test data/Collections-C/configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.68]) 5 | AC_INIT([libcollectc], [0.0.0], [srdjan.panic@ymail.com]) 6 | AC_CONFIG_SRCDIR([src/array.c]) 7 | AC_CONFIG_HEADERS([config.h]) 8 | 9 | #Setup automake 10 | AM_INIT_AUTOMAKE([foreign subdir-objects]) 11 | 12 | #Libtool init 13 | LT_INIT([shared]) 14 | 15 | #Libtool macro dir 16 | AC_CONFIG_MACRO_DIR([m4]) 17 | 18 | # Checks for programs. 19 | AC_PROG_CC 20 | 21 | # Checks for libraries. 22 | 23 | # Checks for header files. 24 | 25 | # Checks for typedefs, structures, and compiler characteristics. 26 | 27 | # Checks for library functions. 28 | 29 | AC_CONFIG_FILES([Makefile src/Makefile test/Makefile]) 30 | AC_OUTPUT 31 | -------------------------------------------------------------------------------- /static test data/Collections-C/install-sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # install - install a program, script, or datafile 3 | 4 | scriptversion=2013-12-25.23; # UTC 5 | 6 | # This originates from X11R5 (mit/util/scripts/install.sh), which was 7 | # later released in X11R6 (xc/config/util/install.sh) with the 8 | # following copyright and license. 9 | # 10 | # Copyright (C) 1994 X Consortium 11 | # 12 | # Permission is hereby granted, free of charge, to any person obtaining a copy 13 | # of this software and associated documentation files (the "Software"), to 14 | # deal in the Software without restriction, including without limitation the 15 | # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16 | # sell copies of the Software, and to permit persons to whom the Software is 17 | # furnished to do so, subject to the following conditions: 18 | # 19 | # The above copyright notice and this permission notice shall be included in 20 | # all copies or substantial portions of the Software. 21 | # 22 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26 | # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27 | # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | # 29 | # Except as contained in this notice, the name of the X Consortium shall not 30 | # be used in advertising or otherwise to promote the sale, use or other deal- 31 | # ings in this Software without prior written authorization from the X Consor- 32 | # tium. 33 | # 34 | # 35 | # FSF changes to this file are in the public domain. 36 | # 37 | # Calling this script install-sh is preferred over install.sh, to prevent 38 | # 'make' implicit rules from creating a file called install from it 39 | # when there is no Makefile. 40 | # 41 | # This script is compatible with the BSD install script, but was written 42 | # from scratch. 43 | 44 | tab=' ' 45 | nl=' 46 | ' 47 | IFS=" $tab$nl" 48 | 49 | # Set DOITPROG to "echo" to test this script. 50 | 51 | doit=${DOITPROG-} 52 | doit_exec=${doit:-exec} 53 | 54 | # Put in absolute file names if you don't have them in your path; 55 | # or use environment vars. 56 | 57 | chgrpprog=${CHGRPPROG-chgrp} 58 | chmodprog=${CHMODPROG-chmod} 59 | chownprog=${CHOWNPROG-chown} 60 | cmpprog=${CMPPROG-cmp} 61 | cpprog=${CPPROG-cp} 62 | mkdirprog=${MKDIRPROG-mkdir} 63 | mvprog=${MVPROG-mv} 64 | rmprog=${RMPROG-rm} 65 | stripprog=${STRIPPROG-strip} 66 | 67 | posix_mkdir= 68 | 69 | # Desired mode of installed file. 70 | mode=0755 71 | 72 | chgrpcmd= 73 | chmodcmd=$chmodprog 74 | chowncmd= 75 | mvcmd=$mvprog 76 | rmcmd="$rmprog -f" 77 | stripcmd= 78 | 79 | src= 80 | dst= 81 | dir_arg= 82 | dst_arg= 83 | 84 | copy_on_change=false 85 | is_target_a_directory=possibly 86 | 87 | usage="\ 88 | Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 89 | or: $0 [OPTION]... SRCFILES... DIRECTORY 90 | or: $0 [OPTION]... -t DIRECTORY SRCFILES... 91 | or: $0 [OPTION]... -d DIRECTORIES... 92 | 93 | In the 1st form, copy SRCFILE to DSTFILE. 94 | In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 95 | In the 4th, create DIRECTORIES. 96 | 97 | Options: 98 | --help display this help and exit. 99 | --version display version info and exit. 100 | 101 | -c (ignored) 102 | -C install only if different (preserve the last data modification time) 103 | -d create directories instead of installing files. 104 | -g GROUP $chgrpprog installed files to GROUP. 105 | -m MODE $chmodprog installed files to MODE. 106 | -o USER $chownprog installed files to USER. 107 | -s $stripprog installed files. 108 | -t DIRECTORY install into DIRECTORY. 109 | -T report an error if DSTFILE is a directory. 110 | 111 | Environment variables override the default commands: 112 | CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG 113 | RMPROG STRIPPROG 114 | " 115 | 116 | while test $# -ne 0; do 117 | case $1 in 118 | -c) ;; 119 | 120 | -C) copy_on_change=true;; 121 | 122 | -d) dir_arg=true;; 123 | 124 | -g) chgrpcmd="$chgrpprog $2" 125 | shift;; 126 | 127 | --help) echo "$usage"; exit $?;; 128 | 129 | -m) mode=$2 130 | case $mode in 131 | *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) 132 | echo "$0: invalid mode: $mode" >&2 133 | exit 1;; 134 | esac 135 | shift;; 136 | 137 | -o) chowncmd="$chownprog $2" 138 | shift;; 139 | 140 | -s) stripcmd=$stripprog;; 141 | 142 | -t) 143 | is_target_a_directory=always 144 | dst_arg=$2 145 | # Protect names problematic for 'test' and other utilities. 146 | case $dst_arg in 147 | -* | [=\(\)!]) dst_arg=./$dst_arg;; 148 | esac 149 | shift;; 150 | 151 | -T) is_target_a_directory=never;; 152 | 153 | --version) echo "$0 $scriptversion"; exit $?;; 154 | 155 | --) shift 156 | break;; 157 | 158 | -*) echo "$0: invalid option: $1" >&2 159 | exit 1;; 160 | 161 | *) break;; 162 | esac 163 | shift 164 | done 165 | 166 | # We allow the use of options -d and -T together, by making -d 167 | # take the precedence; this is for compatibility with GNU install. 168 | 169 | if test -n "$dir_arg"; then 170 | if test -n "$dst_arg"; then 171 | echo "$0: target directory not allowed when installing a directory." >&2 172 | exit 1 173 | fi 174 | fi 175 | 176 | if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then 177 | # When -d is used, all remaining arguments are directories to create. 178 | # When -t is used, the destination is already specified. 179 | # Otherwise, the last argument is the destination. Remove it from $@. 180 | for arg 181 | do 182 | if test -n "$dst_arg"; then 183 | # $@ is not empty: it contains at least $arg. 184 | set fnord "$@" "$dst_arg" 185 | shift # fnord 186 | fi 187 | shift # arg 188 | dst_arg=$arg 189 | # Protect names problematic for 'test' and other utilities. 190 | case $dst_arg in 191 | -* | [=\(\)!]) dst_arg=./$dst_arg;; 192 | esac 193 | done 194 | fi 195 | 196 | if test $# -eq 0; then 197 | if test -z "$dir_arg"; then 198 | echo "$0: no input file specified." >&2 199 | exit 1 200 | fi 201 | # It's OK to call 'install-sh -d' without argument. 202 | # This can happen when creating conditional directories. 203 | exit 0 204 | fi 205 | 206 | if test -z "$dir_arg"; then 207 | if test $# -gt 1 || test "$is_target_a_directory" = always; then 208 | if test ! -d "$dst_arg"; then 209 | echo "$0: $dst_arg: Is not a directory." >&2 210 | exit 1 211 | fi 212 | fi 213 | fi 214 | 215 | if test -z "$dir_arg"; then 216 | do_exit='(exit $ret); exit $ret' 217 | trap "ret=129; $do_exit" 1 218 | trap "ret=130; $do_exit" 2 219 | trap "ret=141; $do_exit" 13 220 | trap "ret=143; $do_exit" 15 221 | 222 | # Set umask so as not to create temps with too-generous modes. 223 | # However, 'strip' requires both read and write access to temps. 224 | case $mode in 225 | # Optimize common cases. 226 | *644) cp_umask=133;; 227 | *755) cp_umask=22;; 228 | 229 | *[0-7]) 230 | if test -z "$stripcmd"; then 231 | u_plus_rw= 232 | else 233 | u_plus_rw='% 200' 234 | fi 235 | cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; 236 | *) 237 | if test -z "$stripcmd"; then 238 | u_plus_rw= 239 | else 240 | u_plus_rw=,u+rw 241 | fi 242 | cp_umask=$mode$u_plus_rw;; 243 | esac 244 | fi 245 | 246 | for src 247 | do 248 | # Protect names problematic for 'test' and other utilities. 249 | case $src in 250 | -* | [=\(\)!]) src=./$src;; 251 | esac 252 | 253 | if test -n "$dir_arg"; then 254 | dst=$src 255 | dstdir=$dst 256 | test -d "$dstdir" 257 | dstdir_status=$? 258 | else 259 | 260 | # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 261 | # might cause directories to be created, which would be especially bad 262 | # if $src (and thus $dsttmp) contains '*'. 263 | if test ! -f "$src" && test ! -d "$src"; then 264 | echo "$0: $src does not exist." >&2 265 | exit 1 266 | fi 267 | 268 | if test -z "$dst_arg"; then 269 | echo "$0: no destination specified." >&2 270 | exit 1 271 | fi 272 | dst=$dst_arg 273 | 274 | # If destination is a directory, append the input filename; won't work 275 | # if double slashes aren't ignored. 276 | if test -d "$dst"; then 277 | if test "$is_target_a_directory" = never; then 278 | echo "$0: $dst_arg: Is a directory" >&2 279 | exit 1 280 | fi 281 | dstdir=$dst 282 | dst=$dstdir/`basename "$src"` 283 | dstdir_status=0 284 | else 285 | dstdir=`dirname "$dst"` 286 | test -d "$dstdir" 287 | dstdir_status=$? 288 | fi 289 | fi 290 | 291 | obsolete_mkdir_used=false 292 | 293 | if test $dstdir_status != 0; then 294 | case $posix_mkdir in 295 | '') 296 | # Create intermediate dirs using mode 755 as modified by the umask. 297 | # This is like FreeBSD 'install' as of 1997-10-28. 298 | umask=`umask` 299 | case $stripcmd.$umask in 300 | # Optimize common cases. 301 | *[2367][2367]) mkdir_umask=$umask;; 302 | .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; 303 | 304 | *[0-7]) 305 | mkdir_umask=`expr $umask + 22 \ 306 | - $umask % 100 % 40 + $umask % 20 \ 307 | - $umask % 10 % 4 + $umask % 2 308 | `;; 309 | *) mkdir_umask=$umask,go-w;; 310 | esac 311 | 312 | # With -d, create the new directory with the user-specified mode. 313 | # Otherwise, rely on $mkdir_umask. 314 | if test -n "$dir_arg"; then 315 | mkdir_mode=-m$mode 316 | else 317 | mkdir_mode= 318 | fi 319 | 320 | posix_mkdir=false 321 | case $umask in 322 | *[123567][0-7][0-7]) 323 | # POSIX mkdir -p sets u+wx bits regardless of umask, which 324 | # is incompatible with FreeBSD 'install' when (umask & 300) != 0. 325 | ;; 326 | *) 327 | tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ 328 | trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 329 | 330 | if (umask $mkdir_umask && 331 | exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 332 | then 333 | if test -z "$dir_arg" || { 334 | # Check for POSIX incompatibilities with -m. 335 | # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or 336 | # other-writable bit of parent directory when it shouldn't. 337 | # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. 338 | ls_ld_tmpdir=`ls -ld "$tmpdir"` 339 | case $ls_ld_tmpdir in 340 | d????-?r-*) different_mode=700;; 341 | d????-?--*) different_mode=755;; 342 | *) false;; 343 | esac && 344 | $mkdirprog -m$different_mode -p -- "$tmpdir" && { 345 | ls_ld_tmpdir_1=`ls -ld "$tmpdir"` 346 | test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" 347 | } 348 | } 349 | then posix_mkdir=: 350 | fi 351 | rmdir "$tmpdir/d" "$tmpdir" 352 | else 353 | # Remove any dirs left behind by ancient mkdir implementations. 354 | rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null 355 | fi 356 | trap '' 0;; 357 | esac;; 358 | esac 359 | 360 | if 361 | $posix_mkdir && ( 362 | umask $mkdir_umask && 363 | $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" 364 | ) 365 | then : 366 | else 367 | 368 | # The umask is ridiculous, or mkdir does not conform to POSIX, 369 | # or it failed possibly due to a race condition. Create the 370 | # directory the slow way, step by step, checking for races as we go. 371 | 372 | case $dstdir in 373 | /*) prefix='/';; 374 | [-=\(\)!]*) prefix='./';; 375 | *) prefix='';; 376 | esac 377 | 378 | oIFS=$IFS 379 | IFS=/ 380 | set -f 381 | set fnord $dstdir 382 | shift 383 | set +f 384 | IFS=$oIFS 385 | 386 | prefixes= 387 | 388 | for d 389 | do 390 | test X"$d" = X && continue 391 | 392 | prefix=$prefix$d 393 | if test -d "$prefix"; then 394 | prefixes= 395 | else 396 | if $posix_mkdir; then 397 | (umask=$mkdir_umask && 398 | $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break 399 | # Don't fail if two instances are running concurrently. 400 | test -d "$prefix" || exit 1 401 | else 402 | case $prefix in 403 | *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; 404 | *) qprefix=$prefix;; 405 | esac 406 | prefixes="$prefixes '$qprefix'" 407 | fi 408 | fi 409 | prefix=$prefix/ 410 | done 411 | 412 | if test -n "$prefixes"; then 413 | # Don't fail if two instances are running concurrently. 414 | (umask $mkdir_umask && 415 | eval "\$doit_exec \$mkdirprog $prefixes") || 416 | test -d "$dstdir" || exit 1 417 | obsolete_mkdir_used=true 418 | fi 419 | fi 420 | fi 421 | 422 | if test -n "$dir_arg"; then 423 | { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && 424 | { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && 425 | { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || 426 | test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 427 | else 428 | 429 | # Make a couple of temp file names in the proper directory. 430 | dsttmp=$dstdir/_inst.$$_ 431 | rmtmp=$dstdir/_rm.$$_ 432 | 433 | # Trap to clean up those temp files at exit. 434 | trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 435 | 436 | # Copy the file name to the temp name. 437 | (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && 438 | 439 | # and set any options; do chmod last to preserve setuid bits. 440 | # 441 | # If any of these fail, we abort the whole thing. If we want to 442 | # ignore errors from any of these, just make sure not to ignore 443 | # errors from the above "$doit $cpprog $src $dsttmp" command. 444 | # 445 | { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && 446 | { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && 447 | { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && 448 | { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && 449 | 450 | # If -C, don't bother to copy if it wouldn't change the file. 451 | if $copy_on_change && 452 | old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && 453 | new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && 454 | set -f && 455 | set X $old && old=:$2:$4:$5:$6 && 456 | set X $new && new=:$2:$4:$5:$6 && 457 | set +f && 458 | test "$old" = "$new" && 459 | $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 460 | then 461 | rm -f "$dsttmp" 462 | else 463 | # Rename the file to the real destination. 464 | $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || 465 | 466 | # The rename failed, perhaps because mv can't rename something else 467 | # to itself, or perhaps because mv is so ancient that it does not 468 | # support -f. 469 | { 470 | # Now remove or move aside any old file at destination location. 471 | # We try this two ways since rm can't unlink itself on some 472 | # systems and the destination file might be busy for other 473 | # reasons. In this case, the final cleanup might fail but the new 474 | # file should still install successfully. 475 | { 476 | test ! -f "$dst" || 477 | $doit $rmcmd -f "$dst" 2>/dev/null || 478 | { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && 479 | { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } 480 | } || 481 | { echo "$0: cannot unlink or rename $dst" >&2 482 | (exit 1); exit 1 483 | } 484 | } && 485 | 486 | # Now rename the file to the real destination. 487 | $doit $mvcmd "$dsttmp" "$dst" 488 | } 489 | fi || exit 1 490 | 491 | trap '' 0 492 | fi 493 | done 494 | 495 | # Local variables: 496 | # eval: (add-hook 'write-file-hooks 'time-stamp) 497 | # time-stamp-start: "scriptversion=" 498 | # time-stamp-format: "%:y-%02m-%02d.%02H" 499 | # time-stamp-time-zone: "UTC" 500 | # time-stamp-end: "; # UTC" 501 | # End: 502 | -------------------------------------------------------------------------------- /static test data/Collections-C/src/Makefile.am: -------------------------------------------------------------------------------- 1 | lib_LTLIBRARIES = libcollectc.la 2 | 3 | libcollectc_la_CFLAGS= -O2 -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wall -pedantic -std=c99 -Wcast-qual -Wshadow 4 | 5 | libcollectc_la_LDFLAGS= -module -avoid-version -shared 6 | 7 | libcollectc_la_SOURCES = array.c stack.c slist.c \ 8 | queue.c hashtable.c hashset.c \ 9 | deque.c list.c common.h \ 10 | array.h list.h slist.h \ 11 | hashtable.h hashset.h deque.h \ 12 | stack.h queue.h treetable.c \ 13 | treetable.h treeset.c treeset.h \ 14 | common.c 15 | 16 | library_includedir = $(includedir)/collectc 17 | 18 | library_include_HEADERS = hashtable.h hashset.h \ 19 | array.h list.h slist.h \ 20 | common.h deque.h queue.h \ 21 | stack.h treetable.h treeset.h 22 | -------------------------------------------------------------------------------- /static test data/Collections-C/src/array.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Collections-C 3 | * Copyright (C) 2013-2015 Srđan Panić 4 | * 5 | * This file is part of Collections-C. 6 | * 7 | * Collections-C is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * Collections-C 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 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Collections-C. If not, see . 19 | */ 20 | 21 | #ifndef COLLECTIONS_C_ARRAY_H 22 | #define COLLECTIONS_C_ARRAY_H 23 | 24 | #include "common.h" 25 | 26 | /** 27 | * A dynamic array that expands automatically as elements are 28 | * added. The array supports amortized constant time insertion 29 | * and removal of elements at the end of the array, as well as 30 | * constant time access. 31 | */ 32 | typedef struct array_s Array; 33 | 34 | /** 35 | * Array configuration structure. Used to initalize a new Array 36 | * with specific values. 37 | */ 38 | typedef struct array_conf_s { 39 | /** 40 | * The initial capacity of the array */ 41 | size_t capacity; 42 | 43 | /** 44 | * The rate at which the buffer expands (capacity * exp_factor). */ 45 | float exp_factor; 46 | 47 | /** 48 | * Memory allocators used to allocate the Array structure and the 49 | * underlying data buffers. */ 50 | void *(*mem_alloc) (size_t size); 51 | void *(*mem_calloc) (size_t blocks, size_t size); 52 | void (*mem_free) (void *block); 53 | } ArrayConf; 54 | 55 | /** 56 | * Array iterator structure. Used to iterate over the elements of 57 | * the array in an ascending order. The iterator also supports 58 | * operations for safely adding and removing elements during 59 | * iteration. 60 | */ 61 | typedef struct array_iter_s { 62 | /** 63 | * The array associated with this iterator */ 64 | Array *ar; 65 | 66 | /** 67 | * The current position of the iterator.*/ 68 | size_t index; 69 | 70 | /** 71 | * Set to true if the last returned element was removed. */ 72 | bool last_removed; 73 | } ArrayIter; 74 | 75 | /** 76 | * Array zip iterator structure. Used to iterate over the elements of two 77 | * arrays in lockstep in an ascending order until one of the Arrays is 78 | * exhausted. The iterator also supports operations for safely adding 79 | * and removing elements during iteration. 80 | */ 81 | typedef struct array_zip_iter_s { 82 | Array *ar1; 83 | Array *ar2; 84 | size_t index; 85 | bool last_removed; 86 | } ArrayZipIter; 87 | 88 | 89 | enum cc_stat array_new (Array **out); 90 | enum cc_stat array_new_conf (ArrayConf const * const conf, Array **out); 91 | void array_conf_init (ArrayConf *conf); 92 | 93 | void array_destroy (Array *ar); 94 | void array_destroy_free (Array *ar); 95 | 96 | enum cc_stat array_add (Array *ar, void *element); 97 | enum cc_stat array_add_at (Array *ar, void *element, size_t index); 98 | enum cc_stat array_replace_at (Array *ar, void *element, size_t index, void **out); 99 | 100 | enum cc_stat array_remove (Array *ar, void *element, void **out); 101 | enum cc_stat array_remove_at (Array *ar, size_t index, void **out); 102 | enum cc_stat array_remove_last (Array *ar, void **out); 103 | void array_remove_all (Array *ar); 104 | void array_remove_all_free (Array *ar); 105 | 106 | enum cc_stat array_get_at (Array *ar, size_t index, void **out); 107 | enum cc_stat array_get_last (Array *ar, void **out); 108 | 109 | enum cc_stat array_subarray (Array *ar, size_t from, size_t to, Array **out); 110 | enum cc_stat array_copy_shallow (Array *ar, Array **out); 111 | enum cc_stat array_copy_deep (Array *ar, void *(*cp) (void*), Array **out); 112 | 113 | void array_reverse (Array *ar); 114 | enum cc_stat array_trim_capacity (Array *ar); 115 | 116 | size_t array_contains (Array *ar, void *element); 117 | size_t array_contains_value (Array *ar, void *element, int (*cmp) (const void*, const void*)); 118 | size_t array_size (Array *ar); 119 | size_t array_capacity (Array *ar); 120 | 121 | enum cc_stat array_index_of (Array *ar, void *element, size_t *index); 122 | void array_sort (Array *ar, int (*cmp) (const void*, const void*)); 123 | 124 | void array_map (Array *ar, void (*fn) (void*)); 125 | void array_reduce (Array *ar, void (*fn) (void*, void*, void*), void *result); 126 | 127 | enum cc_stat array_filter_mut (Array *ar, bool (*predicate) (const void*)); 128 | enum cc_stat array_filter (Array *ar, bool (*predicate) (const void*), Array **out); 129 | 130 | void array_iter_init (ArrayIter *iter, Array *ar); 131 | enum cc_stat array_iter_next (ArrayIter *iter, void **out); 132 | enum cc_stat array_iter_remove (ArrayIter *iter, void **out); 133 | enum cc_stat array_iter_add (ArrayIter *iter, void *element); 134 | enum cc_stat array_iter_replace (ArrayIter *iter, void *element, void **out); 135 | size_t array_iter_index (ArrayIter *iter); 136 | 137 | 138 | void array_zip_iter_init (ArrayZipIter *iter, Array *a1, Array *a2); 139 | enum cc_stat array_zip_iter_next (ArrayZipIter *iter, void **out1, void **out2); 140 | enum cc_stat array_zip_iter_add (ArrayZipIter *iter, void *e1, void *e2); 141 | enum cc_stat array_zip_iter_remove (ArrayZipIter *iter, void **out1, void **out2); 142 | enum cc_stat array_zip_iter_replace(ArrayZipIter *iter, void *e1, void *e2, void **out1, void **out2); 143 | size_t array_zip_iter_index (ArrayZipIter *iter); 144 | 145 | const void* const* array_get_buffer(Array *ar); 146 | 147 | #endif /* COLLECTIONS_C_ARRAY_H */ 148 | -------------------------------------------------------------------------------- /static test data/Collections-C/src/common.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Collections-C 3 | * Copyright (C) 2013-2016 Srđan Panić 4 | * 5 | * This file is part of Collections-C. 6 | * 7 | * Collections-C is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * Collections-C 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 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Collections-C. If not, see . 19 | */ 20 | 21 | 22 | #include "common.h" 23 | 24 | 25 | /** 26 | * String comparator function. 27 | * 28 | * @param[in] str1 first string 29 | * @param[in] str2 second string 30 | * 31 | * @return 32 | */ 33 | int cc_common_cmp_str(const void *str1, const void *str2) 34 | { 35 | return strcmp((const char*) str1, (const char*) str2); 36 | } 37 | 38 | /** 39 | * Pointer comparator function. 40 | * 41 | * @param[in] ptr1 first pointer 42 | * @param[in] ptr2 second pointer 43 | * 44 | * @return 45 | */ 46 | int cc_common_cmp_ptr(const void *ptr1, const void *ptr2) 47 | { 48 | if (ptr1 < ptr2) 49 | return -1; 50 | else if (ptr1 > ptr2) 51 | return 1; 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /static test data/Collections-C/src/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Collections-C 3 | * Copyright (C) 2013-2014 Srđan Panić 4 | * 5 | * This file is part of Collections-C. 6 | * 7 | * Collections-C is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * Collections-C 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 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Collections-C. If not, see . 19 | */ 20 | 21 | #ifndef COLLECTIONS_C_COMMON_H 22 | #define COLLECTIONS_C_COMMON_H 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #ifdef ARCH_64 30 | #define MAX_POW_TWO (((size_t) 1) << 63) 31 | #else 32 | #define MAX_POW_TWO (((size_t) 1) << 31) 33 | #endif /* ARCH_64 */ 34 | 35 | 36 | enum cc_stat { 37 | CC_OK = 0, 38 | 39 | CC_ERR_ALLOC = 1, 40 | CC_ERR_INVALID_CAPACITY = 2, 41 | CC_ERR_INVALID_RANGE = 3, 42 | CC_ERR_MAX_CAPACITY = 4, 43 | CC_ERR_KEY_NOT_FOUND = 6, 44 | CC_ERR_VALUE_NOT_FOUND = 7, 45 | CC_ERR_OUT_OF_RANGE = 8, 46 | 47 | CC_ITER_END = 9, 48 | }; 49 | 50 | #define CC_MAX_ELEMENTS ((size_t) - 2) 51 | 52 | #if defined(_MSC_VER) 53 | 54 | #define INLINE __inline 55 | #define FORCE_INLINE __forceinline 56 | 57 | #else 58 | 59 | #define INLINE inline 60 | #define FORCE_INLINE inline __attribute__((always_inline)) 61 | 62 | #endif /* _MSC_VER */ 63 | 64 | 65 | int cc_common_cmp_str(const void *key1, const void *key2); 66 | int cc_common_cmp_ptr(const void *key1, const void *key2); 67 | 68 | 69 | #define CC_CMP_STRING cc_common_cmp_str 70 | #define CC_CMP_POINTER cc_common_cmp_ptr 71 | 72 | 73 | #endif /* COLLECTIONS_C_COMMON_H */ 74 | -------------------------------------------------------------------------------- /static test data/Collections-C/src/deque.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Collections-C 3 | * Copyright (C) 2013-2015 Srđan Panić 4 | * 5 | * This file is part of Collections-C. 6 | * 7 | * Collections-C is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * Collections-C 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 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Collections-C. If not, see . 19 | */ 20 | 21 | #ifndef COLLECTIONS_C_DEQUE_H 22 | #define COLLECTIONS_C_DEQUE_H 23 | 24 | #include "common.h" 25 | 26 | /** 27 | * A dynamic array that supports amortized constant time insertion 28 | * and removal at both ends and constant time access. 29 | */ 30 | typedef struct deque_s Deque; 31 | 32 | /** 33 | * Deque configuration structure. Used to initialize a new Deque 34 | * with specific values. 35 | */ 36 | typedef struct deque_conf_s { 37 | /** 38 | * The initial capacity of the deque. Must be a power of two. 39 | * if a non power of two is passed, it will be rounded to the 40 | * closest upper power of two */ 41 | size_t capacity; 42 | 43 | /** 44 | * Memory allocators used to allocate the Vector structure and the 45 | * underlying data buffers. */ 46 | void *(*mem_alloc) (size_t size); 47 | void *(*mem_calloc) (size_t blocks, size_t size); 48 | void (*mem_free) (void *block); 49 | } DequeConf; 50 | 51 | /** 52 | * Deque iterator object. Used to iterate over the elements of 53 | * a deque in an ascending order. The iterator also supports 54 | * operations for safely removing and adding elements during 55 | * iteration. 56 | */ 57 | typedef struct deque_iter_s { 58 | /** 59 | * The deque associated with this iterator.*/ 60 | Deque *deque; 61 | 62 | /** 63 | * The current logical position of the iterator. */ 64 | size_t index; 65 | 66 | bool last_removed; 67 | } DequeIter; 68 | 69 | /** 70 | * Deque zip iterator structure. Used to iterate over two Deques in 71 | * lockstep in an ascending order until one of the deques is exhausted. 72 | * The iterator also supports operations for safely adding and removing 73 | * elements during iteration. 74 | */ 75 | typedef struct deque_zip_iter_s { 76 | Deque *d1; 77 | Deque *d2; 78 | size_t index; 79 | bool last_removed; 80 | } DequeZipIter; 81 | 82 | 83 | enum cc_stat deque_new (Deque **deque); 84 | enum cc_stat deque_new_conf (DequeConf const * const conf, Deque **deque); 85 | void deque_conf_init (DequeConf *conf); 86 | 87 | void deque_destroy (Deque *deque); 88 | void deque_destroy_free (Deque *deque); 89 | 90 | enum cc_stat deque_add (Deque *deque, void *element); 91 | enum cc_stat deque_add_first (Deque *deque, void *element); 92 | enum cc_stat deque_add_last (Deque *deque, void *element); 93 | enum cc_stat deque_add_at (Deque *deque, void *element, size_t index); 94 | enum cc_stat deque_replace_at (Deque *deque, void *element, size_t index, void **out); 95 | 96 | enum cc_stat deque_remove (Deque *deque, void *element, void **out); 97 | enum cc_stat deque_remove_at (Deque *deque, size_t index, void **out); 98 | enum cc_stat deque_remove_first (Deque *deque, void **out); 99 | enum cc_stat deque_remove_last (Deque *deque, void **out); 100 | void deque_remove_all (Deque *deque); 101 | void deque_remove_all_free (Deque *deque); 102 | 103 | enum cc_stat deque_get_at (Deque const * const deque, size_t index, void **out); 104 | enum cc_stat deque_get_first (Deque const * const deque, void **out); 105 | enum cc_stat deque_get_last (Deque const * const deque, void **out); 106 | 107 | enum cc_stat deque_copy_shallow (Deque const * const deque, Deque **out); 108 | enum cc_stat deque_copy_deep (Deque const * const deque, void *(*cp) (void*), Deque **out); 109 | 110 | void deque_reverse (Deque *deque); 111 | enum cc_stat deque_trim_capacity (Deque *deque); 112 | 113 | size_t deque_contains (Deque const * const deque, const void *element); 114 | size_t deque_contains_value (Deque const * const deque, const void *element, int (*cmp)(const void*, const void*)); 115 | size_t deque_size (Deque const * const deque); 116 | size_t deque_capacity (Deque const * const deque); 117 | 118 | enum cc_stat deque_index_of (Deque const * const deque, const void *element, size_t *i); 119 | 120 | void deque_foreach (Deque *deque, void (*fn) (void *)); 121 | 122 | void deque_iter_init (DequeIter *iter, Deque *deque); 123 | enum cc_stat deque_iter_next (DequeIter *iter, void **out); 124 | enum cc_stat deque_iter_remove (DequeIter *iter, void **out); 125 | enum cc_stat deque_iter_add (DequeIter *iter, void *element); 126 | enum cc_stat deque_iter_replace (DequeIter *iter, void *replacement, void **out); 127 | size_t deque_iter_index (DequeIter *iter); 128 | 129 | void deque_zip_iter_init (DequeZipIter *iter, Deque *d1, Deque *d2); 130 | enum cc_stat deque_zip_iter_next (DequeZipIter *iter, void **out1, void **out2); 131 | enum cc_stat deque_zip_iter_add (DequeZipIter *iter, void *e1, void *e2); 132 | enum cc_stat deque_zip_iter_remove (DequeZipIter *iter, void **out1, void **out2); 133 | enum cc_stat deque_zip_iter_replace(DequeZipIter *iter, void *e1, void *e2, void **out1, void **out2); 134 | size_t deque_zip_iter_index (DequeZipIter *iter); 135 | 136 | const void* const* deque_get_buffer (Deque const * const deque); 137 | 138 | #endif /* COLLECTIONS_C_DEQUE_H */ 139 | -------------------------------------------------------------------------------- /static test data/Collections-C/src/hashset.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Collections-C 3 | * Copyright (C) 2013-2015 Srđan Panić 4 | * 5 | * This file is part of Collections-C. 6 | * 7 | * Collections-C is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * Collections-C 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 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Collections-C. If not, see . 19 | */ 20 | 21 | #include "hashset.h" 22 | 23 | struct hashset_s { 24 | HashTable *table; 25 | int *dummy; 26 | 27 | void *(*mem_alloc) (size_t size); 28 | void *(*mem_calloc) (size_t blocks, size_t size); 29 | void (*mem_free) (void *block); 30 | }; 31 | 32 | /** 33 | * Initializes the fields of the HashSetConf struct to default values. 34 | * 35 | * @param[in, out] conf the configuration struct that is being initialized 36 | */ 37 | void hashset_conf_init(HashSetConf *conf) 38 | { 39 | hashtable_conf_init(conf); 40 | } 41 | 42 | /** 43 | * Creates a new HashSet and returns a status code. 44 | * 45 | * @note The newly created HashSet will be a set of strings. 46 | * 47 | * @return CC_OK if the creation was successful, or CC_ERR_ALLOC if the memory 48 | * allocation for the new HashSet failed. 49 | */ 50 | enum cc_stat hashset_new(HashSet **hs) 51 | { 52 | HashSetConf hsc; 53 | hashset_conf_init(&hsc); 54 | return hashset_new_conf(&hsc, hs); 55 | } 56 | 57 | /** 58 | * Creates a new empty HashSet based on the specified HashSetConf struct and 59 | * returns a status code. 60 | * 61 | * The HashSet is allocated using the allocators specified in the HashSetConf 62 | * object. The allocation may fail if the underlying allocator fails. 63 | * 64 | * @param[in] conf The hashset configuration object. All fields must be initialized. 65 | * @param[out] out Pointer to where the newly created HashSet is stored 66 | * 67 | * @return CC_OK if the creation was successful, or CC_ERR_ALLOC if the memory 68 | * allocation for the new HashSet structure failed. 69 | */ 70 | enum cc_stat hashset_new_conf(HashSetConf const * const conf, HashSet **hs) 71 | { 72 | HashSet *set = conf->mem_calloc(1, sizeof(HashSet)); 73 | 74 | if (!set) 75 | return CC_ERR_ALLOC; 76 | 77 | HashTable *table; 78 | enum cc_stat stat = hashtable_new_conf(conf, &table); 79 | 80 | if (stat != CC_OK) { 81 | conf->mem_free(set); 82 | return stat; 83 | } 84 | 85 | set->table = table; 86 | set->mem_alloc = conf->mem_alloc; 87 | set->mem_calloc = conf->mem_calloc; 88 | set->mem_free = conf->mem_free; 89 | 90 | /* A dummy pointer that is never actually dereferenced 91 | * that must not be null.*/ 92 | set->dummy = (int*) 1; 93 | *hs = set; 94 | return CC_OK; 95 | } 96 | 97 | /** 98 | * Destroys the specified HashSet structure without destroying the data 99 | * it holds. 100 | * 101 | * @param[in] table HashSet to be destroyed. 102 | */ 103 | void hashset_destroy(HashSet *set) 104 | { 105 | hashtable_destroy(set->table); 106 | set->mem_free(set); 107 | } 108 | 109 | /** 110 | * Adds a new element to the HashSet. 111 | * 112 | * @param[in] set the set to which the element is being added 113 | * @param[in] element the element being added 114 | * 115 | * @return CC_OK if the element was successfully added, or CC_ERR_ALLOC 116 | * if the memory allocation failed. 117 | */ 118 | enum cc_stat hashset_add(HashSet *set, void *element) 119 | { 120 | return hashtable_add(set->table, element, set->dummy); 121 | } 122 | 123 | /** 124 | * Removes the specified element from the HashSet and sets the out 125 | * parameter to its value. 126 | * 127 | * @param[in] set the set from which the element is being removed 128 | * @param[in] element the element being removed 129 | * @param[out] out Pointer to where the removed value is stored, or NULL 130 | * if it is to be ignored 131 | * 132 | * @return CC_OK if the element was successfully removed, or CC_ERR_VALUE_NOT_FOUND 133 | * if the value was not found. 134 | */ 135 | enum cc_stat hashset_remove(HashSet *set, void *element, void **out) 136 | { 137 | return hashtable_remove(set->table, element, out); 138 | } 139 | 140 | /** 141 | * Removes all elements from the specified set. 142 | * 143 | * @param set the set from which all elements are being removed 144 | */ 145 | void hashset_remove_all(HashSet *set) 146 | { 147 | hashtable_remove_all(set->table); 148 | } 149 | 150 | /** 151 | * Checks whether an element is a part of the specified set. 152 | * 153 | * @param[in] set the set being searched for the specified element 154 | * @param[in] element the element being searched for 155 | * 156 | * @return true if the specified element is an element of the set 157 | */ 158 | bool hashset_contains(HashSet *set, void *element) 159 | { 160 | return hashtable_contains_key(set->table, element); 161 | } 162 | 163 | /** 164 | * Returns the size of the specified set. 165 | * 166 | * @param[in] set the set whose size is being returned 167 | * 168 | * @return the size of the set 169 | */ 170 | size_t hashset_size(HashSet *set) 171 | { 172 | return hashtable_size(set->table); 173 | } 174 | 175 | /** 176 | * Returns the capacity of the specified set. 177 | * 178 | * @param[in] set the set whose capacity is being returned 179 | * 180 | * @return the capacity of the set 181 | */ 182 | size_t hashset_capacity(HashSet *set) 183 | { 184 | return hashtable_capacity(set->table); 185 | } 186 | 187 | /** 188 | * Applies the function fn to each element of the HashSet. 189 | * 190 | * @param[in] set the set on which this operation is being performed 191 | * @param[in] fn the operation function that is invoked on each element of the 192 | * set 193 | */ 194 | void hashset_foreach(HashSet *set, void (*fn) (const void *e)) 195 | { 196 | hashtable_foreach_key(set->table, fn); 197 | } 198 | 199 | /** 200 | * Initializes the set iterator. 201 | * 202 | * @param[in] iter the iterator that is being initialized 203 | * @param[in] set the set on which this iterator will operate 204 | */ 205 | void hashset_iter_init(HashSetIter *iter, HashSet *set) 206 | { 207 | hashtable_iter_init(&(iter->iter), set->table); 208 | } 209 | 210 | /** 211 | * Advances the iterator and sets the out parameter to the value of the 212 | * next element. 213 | * 214 | * @param[in] iter the iterator that is being advanced 215 | * @param[out] out Pointer to where the next element is set 216 | * 217 | * @return CC_OK if the iterator was advanced, or CC_ITER_END if the 218 | * end of the HashSet has been reached. 219 | */ 220 | enum cc_stat hashset_iter_next(HashSetIter *iter, void **out) 221 | { 222 | TableEntry *entry; 223 | enum cc_stat status = hashtable_iter_next(&(iter->iter), &entry); 224 | 225 | if (status != CC_OK) 226 | return status; 227 | 228 | if (out) 229 | *out = entry->key; 230 | 231 | return CC_OK; 232 | } 233 | 234 | /** 235 | * Removes the last returned entry by hashset_iter_next() 236 | * function without invalidating the iterator and optionally sets the 237 | * out parameter to the value of the removed element. 238 | * 239 | * @note This Function should only ever be called after a call to 240 | * hashset_iter_next(). 241 | * 242 | * @param[in] iter The iterator on which this operation is performed 243 | * @param[out] out Pointer to where the removed element is stored, or NULL 244 | * if it is to be ignored 245 | * 246 | * @return CC_OK if the entry was successfully removed, or 247 | * CC_ERR_VALUE_NOT_FOUND. 248 | */ 249 | enum cc_stat hashset_iter_remove(HashSetIter *iter, void **out) 250 | { 251 | return hashtable_iter_remove(&(iter->iter), out); 252 | } 253 | -------------------------------------------------------------------------------- /static test data/Collections-C/src/hashset.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Collections-C 3 | * Copyright (C) 2013-2015 Srđan Panić 4 | * 5 | * This file is part of Collections-C. 6 | * 7 | * Collections-C is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * Collections-C 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 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Collections-C. If not, see . 19 | */ 20 | 21 | #ifndef COLLECTIONS_C_HASHSET_H 22 | #define COLLECTIONS_C_HASHSET_H 23 | 24 | #include "common.h" 25 | #include "hashtable.h" 26 | 27 | /** 28 | * An unordered set. The lookup, deletion, and insertion are 29 | * performed in amortized constant time and in the worst case 30 | * in amortized linear time. 31 | */ 32 | typedef struct hashset_s HashSet; 33 | 34 | /** 35 | * HashSet configuration object. 36 | */ 37 | typedef HashTableConf HashSetConf; 38 | 39 | /** 40 | * HashSet iterator structure. Used to iterate over the elements 41 | * of the HashSet. The iterator also supports operations for safely 42 | * removing elements during iteration. 43 | */ 44 | typedef struct hashset_iter_s { 45 | HashTableIter iter; 46 | } HashSetIter; 47 | 48 | void hashset_conf_init (HashSetConf *conf); 49 | 50 | enum cc_stat hashset_new (HashSet **hs); 51 | enum cc_stat hashset_new_conf (HashSetConf const * const conf, HashSet **hs); 52 | void hashset_destroy (HashSet *set); 53 | 54 | enum cc_stat hashset_add (HashSet *set, void *element); 55 | enum cc_stat hashset_remove (HashSet *set, void *element, void **out); 56 | void hashset_remove_all (HashSet *set); 57 | 58 | bool hashset_contains (HashSet *set, void *element); 59 | size_t hashset_size (HashSet *set); 60 | size_t hashset_capacity (HashSet *set); 61 | 62 | void hashset_foreach (HashSet *set, void (*op) (const void*)); 63 | 64 | void hashset_iter_init (HashSetIter *iter, HashSet *set); 65 | enum cc_stat hashset_iter_next (HashSetIter *iter, void **out); 66 | enum cc_stat hashset_iter_remove (HashSetIter *iter, void **out); 67 | 68 | #endif /* COLLECTIONS_C_HASHSET_H */ 69 | -------------------------------------------------------------------------------- /static test data/Collections-C/src/hashtable.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Collections-C 3 | * Copyright (C) 2013-2015 Srđan Panić 4 | * 5 | * This file is part of Collections-C. 6 | * 7 | * Collections-C is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * Collections-C 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 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Collections-C. If not, see . 19 | */ 20 | 21 | #ifndef COLLECTIONS_C_HASHTABLE_H 22 | #define COLLECTIONS_C_HASHTABLE_H 23 | 24 | #include "array.h" 25 | #include "common.h" 26 | 27 | #define KEY_LENGTH_VARIABLE -1 28 | #define KEY_LENGTH_POINTER sizeof(void*) 29 | 30 | /** 31 | * An unordered key-value map. HashTable supports best case amortized 32 | * constant time insertion, removal, and lookup of values. The worst 33 | * case complexity for these operations is amortized linear time. 34 | * The performance of the table depends greatly on the quality of the 35 | * hash function being used. 36 | */ 37 | typedef struct hashtable_s HashTable; 38 | 39 | /** 40 | * A HashTable table entry. 41 | * 42 | * @note modifying this structure may invalidate the table. 43 | */ 44 | typedef struct table_entry_s { 45 | /** 46 | * A key in the table */ 47 | void *key; 48 | 49 | /** 50 | * Value associated with the key */ 51 | void *value; 52 | 53 | /** 54 | * Hash of the key */ 55 | size_t hash; 56 | 57 | /** 58 | * Pointer the next entry in the list. */ 59 | struct table_entry_s *next; 60 | } TableEntry; 61 | 62 | /** 63 | * HashTable iterator object. Used to iterate over the entries of 64 | * the table in an undefined order. The iterator also supports operations 65 | * for safely removing elements during iteration. 66 | * 67 | * @note This structure should only be modified through the iterator functions. 68 | */ 69 | typedef struct hashtable_iter { 70 | HashTable *table; 71 | size_t bucket_index; 72 | TableEntry *prev_entry; 73 | TableEntry *next_entry; 74 | } HashTableIter; 75 | 76 | /** 77 | * HashTable configuration object. Used to initialize a new HashTable 78 | * with specific values. 79 | */ 80 | typedef struct hashtable_conf_s { 81 | /** 82 | * The load factor determines how the underlying 83 | * table array grows. For example if the load factor 84 | * is 0.5 and the arrays capacity is 100, the resize will 85 | * be triggered once the 50th entry is added. */ 86 | float load_factor; 87 | 88 | /** 89 | * The initial capacity of the table array. */ 90 | size_t initial_capacity; 91 | 92 | /** 93 | * Length of the key or -1 if the key length is 94 | * variable */ 95 | int key_length; 96 | 97 | /** 98 | * The hash seed passed to the hash function for 99 | * extra 'randomness'.*/ 100 | uint32_t hash_seed; 101 | 102 | /** 103 | * Hash function used for hashing table keys */ 104 | size_t (*hash) (const void *key, int l, uint32_t seed); 105 | 106 | /** 107 | * The key comparator function */ 108 | int (*key_compare) (const void *key1, const void *key2); 109 | 110 | /** 111 | * Memory allocators used to allocate the HashTable structure 112 | * and for all internal memory allocations. */ 113 | void *(*mem_alloc) (size_t size); 114 | void *(*mem_calloc) (size_t blocks, size_t size); 115 | void (*mem_free) (void *block); 116 | } HashTableConf; 117 | 118 | 119 | void hashtable_conf_init (HashTableConf *conf); 120 | enum cc_stat hashtable_new (HashTable **out); 121 | enum cc_stat hashtable_new_conf (HashTableConf const * const conf, HashTable **out); 122 | 123 | void hashtable_destroy (HashTable *table); 124 | enum cc_stat hashtable_add (HashTable *table, void *key, void *val); 125 | enum cc_stat hashtable_get (HashTable *table, void *key, void **out); 126 | enum cc_stat hashtable_remove (HashTable *table, void *key, void **out); 127 | void hashtable_remove_all (HashTable *table); 128 | bool hashtable_contains_key (HashTable *table, void *key); 129 | 130 | size_t hashtable_size (HashTable *table); 131 | size_t hashtable_capacity (HashTable *table); 132 | 133 | enum cc_stat hashtable_get_keys (HashTable *table, Array **out); 134 | enum cc_stat hashtable_get_values (HashTable *table, Array **out); 135 | 136 | size_t hashtable_hash_string (const void *key, int len, uint32_t seed); 137 | size_t hashtable_hash (const void *key, int len, uint32_t seed); 138 | size_t hashtable_hash_ptr (const void *key, int len, uint32_t seed); 139 | 140 | void hashtable_foreach_key (HashTable *table, void (*op) (const void *)); 141 | void hashtable_foreach_value (HashTable *table, void (*op) (void *)); 142 | 143 | void hashtable_iter_init (HashTableIter *iter, HashTable *table); 144 | enum cc_stat hashtable_iter_next (HashTableIter *iter, TableEntry **out); 145 | enum cc_stat hashtable_iter_remove (HashTableIter *iter, void **out); 146 | 147 | 148 | #define GENERAL_HASH hashtable_hash 149 | #define STRING_HASH hashtable_hash_string 150 | #define POINTER_HASH hashtable_hash_ptr 151 | 152 | 153 | #endif /* COLLECTIONS_C_HASHTABLE_H */ 154 | -------------------------------------------------------------------------------- /static test data/Collections-C/src/list.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Collections-C 3 | * Copyright (C) 2013-2015 Srđan Panić 4 | * 5 | * This file is part of Collections-C. 6 | * 7 | * Collections-C is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * Collections-C 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 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Collections-C. If not, see . 19 | */ 20 | 21 | #ifndef COLLECTIONS_C_LIST_H 22 | #define COLLECTIONS_C_LIST_H 23 | 24 | #include "common.h" 25 | 26 | /** 27 | * A doubly linked list. List is a sequential structure that 28 | * supports insertion, deletion and lookup from both ends in 29 | * constant time, while the worst case is O(n/2) at the middle 30 | * of the list. 31 | */ 32 | typedef struct list_s List; 33 | 34 | /** 35 | * List node. 36 | * 37 | * @note Modifying the links may invalidate the list structure. 38 | */ 39 | typedef struct node_s { 40 | void *data; 41 | struct node_s *next; 42 | struct node_s *prev; 43 | } Node; 44 | 45 | /** 46 | * List iterator structure. Used to iterate over the elements of the 47 | * list in an ascending or descending order. The iterator also supports 48 | * operations for safely adding and removing elements during iteration. 49 | */ 50 | typedef struct list_iter_s { 51 | /** 52 | * The current position of the iterator.*/ 53 | size_t index; 54 | 55 | /** 56 | * The list associated with this iterator */ 57 | List *list; 58 | 59 | /** 60 | * Last returned node */ 61 | Node *last; 62 | 63 | /** 64 | * Next node in the sequence. */ 65 | Node *next; 66 | } ListIter; 67 | 68 | /** 69 | * List zip iterator structure. Used to iterate over two Lists in 70 | * lockstep in an ascending order until one of the lists is exhausted. 71 | * The iterator also supports operations for safely adding and 72 | * removing elements during iteration. 73 | */ 74 | typedef struct list_zip_iter_s { 75 | List *l1; 76 | List *l2; 77 | Node *l1_last; 78 | Node *l2_last; 79 | Node *l1_next; 80 | Node *l2_next; 81 | size_t index; 82 | } ListZipIter; 83 | 84 | 85 | /** 86 | * List configuration structure. Used to initialize a new List with specific 87 | * values. 88 | */ 89 | typedef struct list_conf_s { 90 | void *(*mem_alloc) (size_t size); 91 | void *(*mem_calloc) (size_t blocks, size_t size); 92 | void (*mem_free) (void *block); 93 | } ListConf; 94 | 95 | 96 | void list_conf_init (ListConf *conf); 97 | enum cc_stat list_new (List **list); 98 | enum cc_stat list_new_conf (ListConf const * const conf, List **list); 99 | void list_destroy (List *list); 100 | void list_destroy_free (List *list); 101 | 102 | enum cc_stat list_splice (List *list1, List *list2); 103 | enum cc_stat list_splice_at (List *list, List *list2, size_t index); 104 | 105 | enum cc_stat list_add (List *list, void *element); 106 | enum cc_stat list_add_at (List *list, void *element, size_t index); 107 | enum cc_stat list_add_all (List *list1, List *list2); 108 | enum cc_stat list_add_all_at (List *list, List *list2, size_t index); 109 | enum cc_stat list_add_first (List *list, void *element); 110 | enum cc_stat list_add_last (List *list, void *element); 111 | 112 | enum cc_stat list_remove (List *list, void *element, void **out); 113 | enum cc_stat list_remove_first (List *list, void **out); 114 | enum cc_stat list_remove_last (List *list, void **out); 115 | enum cc_stat list_remove_at (List *list, size_t index, void **out); 116 | 117 | enum cc_stat list_remove_all (List *list); 118 | enum cc_stat list_remove_all_free (List *list); 119 | 120 | enum cc_stat list_get_at (List *list, size_t index, void **out); 121 | enum cc_stat list_get_first (List *list, void **out); 122 | enum cc_stat list_get_last (List *list, void **out); 123 | 124 | enum cc_stat list_sublist (List *list, size_t from, size_t to, List **out); 125 | enum cc_stat list_copy_shallow (List *list, List **out); 126 | enum cc_stat list_copy_deep (List *list, void *(*cp) (void*), List **out); 127 | 128 | enum cc_stat list_replace_at (List *list, void *element, size_t index, void **out); 129 | 130 | size_t list_contains (List *list, void *element); 131 | size_t list_contains_value (List *list, void *element, int (*cmp) (const void*, const void*)); 132 | enum cc_stat list_index_of (List *list, void *element, int (*cmp) (const void*, const void*), size_t *index); 133 | enum cc_stat list_to_array (List *list, void ***out); 134 | 135 | void list_reverse (List *list); 136 | enum cc_stat list_sort (List *list, int (*cmp) (void const*, void const*)); 137 | void list_sort_in_place (List *list, int (*cmp) (void const*, void const*)); 138 | size_t list_size (List *list); 139 | 140 | void list_foreach (List *list, void (*op) (void *)); 141 | 142 | void list_iter_init (ListIter *iter, List *list); 143 | enum cc_stat list_iter_remove (ListIter *iter, void **out); 144 | enum cc_stat list_iter_add (ListIter *iter, void *element); 145 | enum cc_stat list_iter_replace (ListIter *iter, void *element, void **out); 146 | size_t list_iter_index (ListIter *iter); 147 | enum cc_stat list_iter_next (ListIter *iter, void **out); 148 | 149 | void list_diter_init (ListIter *iter, List *list); 150 | enum cc_stat list_diter_remove (ListIter *iter, void **out); 151 | enum cc_stat list_diter_add (ListIter *iter, void *element); 152 | enum cc_stat list_diter_replace (ListIter *iter, void *element, void **out); 153 | size_t list_diter_index (ListIter *iter); 154 | enum cc_stat list_diter_next (ListIter *iter, void **out); 155 | 156 | void list_zip_iter_init (ListZipIter *iter, List *l1, List *l2); 157 | enum cc_stat list_zip_iter_next (ListZipIter *iter, void **out1, void **out2); 158 | enum cc_stat list_zip_iter_add (ListZipIter *iter, void *e1, void *e2); 159 | enum cc_stat list_zip_iter_remove (ListZipIter *iter, void **out1, void **out2); 160 | enum cc_stat list_zip_iter_replace(ListZipIter *iter, void *e1, void *e2, void **out1, void **out2); 161 | size_t list_zip_iter_index (ListZipIter *iter); 162 | 163 | #endif /* COLLECTIONS_C_LIST_H */ 164 | -------------------------------------------------------------------------------- /static test data/Collections-C/src/queue.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Collections-C 3 | * Copyright (C) 2013-2015 Srđan Panić 4 | * 5 | * This file is part of Collections-C. 6 | * 7 | * Collections-C is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * Collections-C 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 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Collections-C. If not, see . 19 | */ 20 | 21 | #include "queue.h" 22 | 23 | struct queue_s { 24 | Deque *d; 25 | 26 | void *(*mem_alloc) (size_t size); 27 | void *(*mem_calloc) (size_t blocks, size_t size); 28 | void (*mem_free) (void *block); 29 | }; 30 | 31 | /** 32 | * Initializes the fields of the QueueConf struct to default values. 33 | * 34 | * @param[in, out] conf the configuration struct that is being initialized 35 | */ 36 | void queue_conf_init(QueueConf *conf) 37 | { 38 | deque_conf_init(conf); 39 | } 40 | 41 | /** 42 | * Creates a new empty queue and returns a status code. 43 | * 44 | * @param[out] out pointer to where the newly created Queue is to be stored 45 | * 46 | * @return CC_OK if the creation was successful, or CC_ERR_ALLOC if the 47 | * memory allocation for the new Queue structure failed. 48 | */ 49 | enum cc_stat queue_new(Queue **queue) 50 | { 51 | QueueConf conf; 52 | queue_conf_init(&conf); 53 | return queue_new_conf(&conf, queue); 54 | } 55 | 56 | /** 57 | * Creates a new empty Queue based on the specified QueueConf object and 58 | * returns a status code. 59 | * 60 | * The Queue is allocated using the allocators specified in the QueueConf struct. 61 | * The allocation may fail if the underlying allocator fails. 62 | * 63 | * @param[in] conf Queue configuration structure. All fields must be initialized 64 | * with appropriate values. 65 | * @param[out] out Pointer to where the newly created Queue is to be stored. 66 | * 67 | * @return CC_OK if the creation was successful, or CC_ERR_ALLOC if the memory 68 | * allocation for the new Queue structure failed. 69 | */ 70 | enum cc_stat queue_new_conf(QueueConf const * const conf, Queue **q) 71 | { 72 | Queue *queue = conf->mem_calloc(1, sizeof(Queue)); 73 | 74 | if (!queue) 75 | return CC_ERR_ALLOC; 76 | 77 | Deque *deque; 78 | deque_new_conf(conf, &deque); 79 | 80 | if (!deque) { 81 | conf->mem_free(queue); 82 | return CC_ERR_ALLOC; 83 | } 84 | 85 | queue->d = deque; 86 | queue->mem_alloc = conf->mem_alloc; 87 | queue->mem_calloc = conf->mem_calloc; 88 | queue->mem_free = conf->mem_free; 89 | 90 | *q = queue; 91 | 92 | return CC_OK; 93 | } 94 | 95 | /** 96 | * Destroys the queue structure, but leaves the data it used to hold intact. 97 | * 98 | * @param[in] queue the queue that is to be destroyed 99 | */ 100 | void queue_destroy(Queue *queue) 101 | { 102 | deque_destroy(queue->d); 103 | queue->mem_free(queue); 104 | } 105 | 106 | /** 107 | * Destroys the queue structure along with all the data it holds. 108 | * 109 | * @note This function should not be called on a queue that has some of its 110 | * elements allocated on the stack. 111 | * 112 | * @param[in] queue the queue that is to be destroyed 113 | */ 114 | void queue_destroy_free(Queue *queue) 115 | { 116 | deque_destroy_free(queue->d); 117 | free(queue); 118 | } 119 | 120 | /** 121 | * Gets the element at the front of the queue and sets the out 122 | * parameter to its value. 123 | * 124 | * @param[in] queue the Queue whose element is being returned 125 | * @param[out] out pointer to where the element is stored 126 | * 127 | * @return CC_OK if the element was found, or CC_ERR_OUT_OF_RANGE if the 128 | * Queue is empty. 129 | */ 130 | enum cc_stat queue_peek(Queue const * const queue, void **out) 131 | { 132 | return deque_get_last(queue->d, out); 133 | } 134 | 135 | /** 136 | * Gets and removes the element at the front of the queue and optionally 137 | * sets the out parameter to the value of the removed element. 138 | * 139 | * @param[in] queue the queue on which this operation is performed 140 | * @param[out] out pointer to where the removed element is stored 141 | * 142 | * @return CC_OK if the element was found, or CC_ERR_OUT_OF_RANGE if the 143 | * Queue is empty. 144 | */ 145 | enum cc_stat queue_poll(Queue *queue, void **out) 146 | { 147 | return deque_remove_last(queue->d, out); 148 | } 149 | 150 | /** 151 | * Appends an element to the back of the queue. This operation may 152 | * fail if the memory allocation for the new element fails. 153 | * 154 | * @param[in] queue the queue on which this operation is performed 155 | * @param[in] element the element being enqueued 156 | * 157 | * @return CC_OK if the element was successfully added, or CC_ERR_ALLOC 158 | * if the memory allocation for the new element failed. 159 | */ 160 | enum cc_stat queue_enqueue(Queue *queue, void *element) 161 | { 162 | return deque_add_first(queue->d, element); 163 | } 164 | 165 | /** 166 | * Returns the size of the specified queue. The size of the queue is 167 | * the number of elements contained within the queue. 168 | * 169 | * @param[in] queue the queue whose size is being returned 170 | * 171 | * @return the number of elements within the queue. 172 | */ 173 | size_t queue_size(Queue const * const queue) 174 | { 175 | return deque_size(queue->d); 176 | } 177 | 178 | /** 179 | * Applies the function fn to each element of the Queue. 180 | * 181 | * @param[in] queue the queue on which this operation is performed 182 | * @param[in] fn the operation function that is to be invoked on each queue element 183 | */ 184 | void queue_foreach(Queue *queue, void (*fn) (void*)) 185 | { 186 | deque_foreach(queue->d, fn); 187 | } 188 | 189 | /** 190 | * Initializes the iterator. 191 | * 192 | * @param[in] iter the iterator that is being initialized 193 | * @param[in] queue the queue to iterate over 194 | */ 195 | void queue_iter_init(QueueIter *iter, Queue *queue) 196 | { 197 | deque_iter_init(&(iter->i), queue->d); 198 | } 199 | 200 | /** 201 | * Advances the iterator and sets the out parameter to the value of the 202 | * next element in the sequence. 203 | * 204 | * @param[in] iter the iterator that is being advanced 205 | * @param[out] out pointer to where the next element is set 206 | * 207 | * @return CC_OK if the iterator was advanced, or CC_ITER_END if the 208 | * end of the Queue has been reached. 209 | */ 210 | enum cc_stat queue_iter_next(QueueIter *iter, void **out) 211 | { 212 | return deque_iter_next(&(iter->i), out); 213 | } 214 | 215 | /** 216 | * Replaces the last returned element by queue_iter_next() 217 | * with the specified element and optionally sets the out parameter to 218 | * the value of the replaced element. 219 | * 220 | * @note This function should only ever be called after a call to 221 | * queue_iter_next(). 222 | * 223 | * @param[in] iter the iterator on which this operation is being performed 224 | * @param[in] element the replacement element 225 | * @param[out] out pointer to where the replaced element is stored, or NULL 226 | * if it is to be ignored 227 | * 228 | * @return CC_OK if the element was replaced successfully, or 229 | * CC_ERR_OUT_OF_RANGE. 230 | */ 231 | enum cc_stat queue_iter_replace(QueueIter *iter, void *replacement, void **out) 232 | { 233 | return deque_iter_replace(&(iter->i), replacement, out); 234 | } 235 | 236 | /** 237 | * Initializes the zip iterator. 238 | * 239 | * @param[in] iter iterator that is being initialized 240 | * @param[in] q1 first queue 241 | * @param[in] q2 second queue 242 | */ 243 | void queue_zip_iter_init(QueueZipIter *iter, Queue *q1, Queue *q2) 244 | { 245 | deque_zip_iter_init(&(iter->i), q1->d, q2->d); 246 | } 247 | 248 | /** 249 | * Outputs the next element pair in the sequence and advances the iterator. 250 | * 251 | * @param[in] iter iterator that is being advanced 252 | * @param[out] out1 output of the first queue element 253 | * @param[out] out2 output of the second queue element 254 | * 255 | * @return CC_OK if a next element pair is returned, or CC_ITER_END if the end 256 | * of one of the queues has been reached. 257 | */ 258 | enum cc_stat queue_zip_iter_next(QueueZipIter *iter, void **out1, void **out2) 259 | { 260 | return deque_zip_iter_next(&(iter->i), out1, out2); 261 | } 262 | 263 | /** 264 | * Replaces the last returned element pair by queue_zip_iter_next() 265 | * with the specified replacement element pair. 266 | * 267 | * @param[in] iter iterator on which this operation is being performed 268 | * @param[in] e1 first queue's replacement element 269 | * @param[in] e2 second queue's replacement element 270 | * @param[out] out1 output of the replaced element from the first queue 271 | * @param[out] out2 output of the replaced element from the second queue 272 | * 273 | * @return CC_OK if the element was successfully replaced, or CC_ERR_OUT_OF_RANGE. 274 | */ 275 | enum cc_stat queue_zip_iter_replace(QueueZipIter *iter, void *e1, void *e2, void **out1, void **out2) 276 | { 277 | return deque_zip_iter_replace(&(iter->i), e1, e2, out1, out2); 278 | } 279 | -------------------------------------------------------------------------------- /static test data/Collections-C/src/queue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Collections-C 3 | * Copyright (C) 2013-2015 Srđan Panić 4 | * 5 | * This file is part of Collections-C. 6 | * 7 | * Collections-C is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * Collections-C 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 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Collections-C. If not, see . 19 | */ 20 | 21 | #ifndef COLLECTIONS_C_QUEUE_H 22 | #define COLLECTIONS_C_QUEUE_H 23 | 24 | #include "common.h" 25 | #include "deque.h" 26 | 27 | /** 28 | * A FIFO (first in first out) structure. Supports constant time 29 | * insertion, removal and lookup. 30 | */ 31 | typedef struct queue_s Queue; 32 | 33 | /** 34 | * Queue configuration object. 35 | */ 36 | typedef DequeConf QueueConf; 37 | 38 | /** 39 | * Queue iterator object. Used to iterate over the elements of a 40 | * queue in an ascending order. 41 | */ 42 | typedef struct queue_iter_s { 43 | DequeIter i; 44 | } QueueIter; 45 | 46 | /** 47 | * Queue zip iterator structure. Used to iterate over the elements of two 48 | * queues in lockstep in an ascending order until one of the queues is 49 | * exhausted. The iterator also supports operations for safely adding 50 | * and removing elements during iteration. 51 | */ 52 | typedef struct queue_zip_iter_s { 53 | DequeZipIter i; 54 | } QueueZipIter; 55 | 56 | 57 | void queue_conf_init (QueueConf *conf); 58 | enum cc_stat queue_new (Queue **q); 59 | enum cc_stat queue_new_conf (QueueConf const * const conf, Queue **q); 60 | void queue_destroy (Queue *queue); 61 | void queue_destroy_free (Queue *queue); 62 | 63 | enum cc_stat queue_peek (Queue const * const queue, void **out); 64 | enum cc_stat queue_poll (Queue *queue, void **out); 65 | enum cc_stat queue_enqueue (Queue *queue, void *element); 66 | 67 | size_t queue_size (Queue const * const queue); 68 | void queue_foreach (Queue *queue, void (*op) (void*)); 69 | 70 | void queue_iter_init (QueueIter *iter, Queue *queue); 71 | enum cc_stat queue_iter_next (QueueIter *iter, void **out); 72 | enum cc_stat queue_iter_replace (QueueIter *iter, void *replacement, void **out); 73 | 74 | void queue_zip_iter_init (QueueZipIter *iter, Queue *q1, Queue *q2); 75 | enum cc_stat queue_zip_iter_next (QueueZipIter *iter, void **out1, void **out2); 76 | enum cc_stat queue_zip_iter_replace(QueueZipIter *iter, void *e1, void *e2, void **out1, void **out2); 77 | 78 | #endif /* COLLECTIONS_C_QUEUE_H */ 79 | -------------------------------------------------------------------------------- /static test data/Collections-C/src/slist.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Collections-C 3 | * Copyright (C) 2013-2015 Srđan Panić 4 | * 5 | * This file is part of Collections-C. 6 | * 7 | * Collections-C is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * Collections-C 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 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Collections-C. If not, see . 19 | */ 20 | 21 | #ifndef COLLECTIONS_C_SLIST_H 22 | #define COLLECTIONS_C_SLIST_H 23 | 24 | #include "common.h" 25 | 26 | /** 27 | * A singly linked list. List is a sequential structure that 28 | * supports constant time insertion, deletion and lookup at 29 | * the beginning of the list, while the worst case for these 30 | * operations is linear time. 31 | */ 32 | typedef struct slist_s SList; 33 | 34 | /** 35 | * SList node. 36 | * 37 | * @note Modifying the links may invalidate the list structure. 38 | */ 39 | typedef struct snode_s { 40 | void *data; 41 | struct snode_s *next; 42 | } SNode; 43 | 44 | /** 45 | * SList iterator structure. Used to iterate over the elements 46 | * of the list in an ascending order. The iterator also supports 47 | * operations for safely adding and removing elements during iteration. 48 | */ 49 | typedef struct slist_iter_s { 50 | size_t index; 51 | SList *list; 52 | SNode *next; 53 | SNode *current; 54 | SNode *prev; 55 | } SListIter; 56 | 57 | /** 58 | * SList zip iterator structure. Used to iterate over two SLists in 59 | * lockstep in an ascending order until one of the lists is exhausted. 60 | * The iterator also supports operations for safely adding and 61 | * removing elements during iteration. 62 | */ 63 | typedef struct slist_zip_iter_s { 64 | size_t index; 65 | SList *l1; 66 | SList *l2; 67 | SNode *l1_next; 68 | SNode *l2_next; 69 | SNode *l1_current; 70 | SNode *l2_current; 71 | SNode *l1_prev; 72 | SNode *l2_prev; 73 | } SListZipIter; 74 | 75 | 76 | /** 77 | * SList configuration structure. Used to initialize a new SList with 78 | * specific values. 79 | */ 80 | typedef struct slist_conf_s { 81 | void *(*mem_alloc) (size_t size); 82 | void *(*mem_calloc) (size_t blocks, size_t size); 83 | void (*mem_free) (void *block); 84 | } SListConf; 85 | 86 | 87 | void slist_conf_init (SListConf *conf); 88 | enum cc_stat slist_new (SList **list); 89 | enum cc_stat slist_new_conf (SListConf const * const conf, SList **list); 90 | void slist_destroy (SList *list); 91 | void slist_destroy_free (SList *list); 92 | 93 | enum cc_stat slist_splice (SList *list1, SList *list2); 94 | enum cc_stat slist_splice_at (SList *list1, SList *list2, size_t index); 95 | 96 | enum cc_stat slist_add (SList *list, void *element); 97 | enum cc_stat slist_add_at (SList *list, void *element, size_t index); 98 | enum cc_stat slist_add_all (SList *list1, SList *list2); 99 | enum cc_stat slist_add_all_at (SList *list1, SList *list2, size_t index); 100 | enum cc_stat slist_add_first (SList *list, void *element); 101 | enum cc_stat slist_add_last (SList *list, void *element); 102 | 103 | enum cc_stat slist_remove (SList *list, void *element, void **out); 104 | enum cc_stat slist_remove_first (SList *list, void **out); 105 | enum cc_stat slist_remove_last (SList *list, void **out); 106 | enum cc_stat slist_remove_at (SList *list, size_t index, void **out); 107 | 108 | enum cc_stat slist_remove_all (SList *list); 109 | enum cc_stat slist_remove_all_free (SList *list); 110 | 111 | enum cc_stat slist_get_at (SList *list, size_t index, void **out); 112 | enum cc_stat slist_get_first (SList *list, void **out); 113 | enum cc_stat slist_get_last (SList *list, void **out); 114 | 115 | enum cc_stat slist_sublist (SList *list, size_t from, size_t to, SList **out); 116 | enum cc_stat slist_copy_shallow (SList *list, SList **out); 117 | enum cc_stat slist_copy_deep (SList *list, void *(*cp) (void*), SList **out); 118 | 119 | enum cc_stat slist_replace_at (SList *list, void *element, size_t index, void **out); 120 | 121 | size_t slist_contains (SList *list, void *element); 122 | size_t slist_contains_value (SList *list, void *element, int (*cmp) (const void*, const void*)); 123 | enum cc_stat slist_index_of (SList *list, void *element, size_t *index); 124 | enum cc_stat slist_to_array (SList *list, void ***out); 125 | 126 | void slist_reverse (SList *list); 127 | enum cc_stat slist_sort (SList *list, int (*cmp) (void const*, void const*)); 128 | size_t slist_size (SList *list); 129 | 130 | void slist_foreach (SList *list, void (*op) (void *)); 131 | 132 | void slist_iter_init (SListIter *iter, SList *list); 133 | enum cc_stat slist_iter_remove (SListIter *iter, void **out); 134 | enum cc_stat slist_iter_add (SListIter *iter, void *element); 135 | enum cc_stat slist_iter_replace (SListIter *iter, void *element, void **out); 136 | enum cc_stat slist_iter_next (SListIter *iter, void **out); 137 | size_t slist_iter_index (SListIter *iter); 138 | 139 | void slist_zip_iter_init (SListZipIter *iter, SList *l1, SList *l2); 140 | enum cc_stat slist_zip_iter_next (SListZipIter *iter, void **out1, void **out2); 141 | enum cc_stat slist_zip_iter_add (SListZipIter *iter, void *e1, void *e2); 142 | enum cc_stat slist_zip_iter_remove (SListZipIter *iter, void **out1, void **out2); 143 | enum cc_stat slist_zip_iter_replace(SListZipIter *iter, void *e1, void *e2, void **out1, void **out2); 144 | size_t slist_zip_iter_index (SListZipIter *iter); 145 | 146 | 147 | #endif /* COLLECTIONS_C_SLIST_H */ 148 | -------------------------------------------------------------------------------- /static test data/Collections-C/src/stack.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Collections-C 3 | * Copyright (C) 2013-2014 Srđan Panić 4 | * 5 | * This file is part of Collections-C. 6 | * 7 | * Collections-C is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * Collections-C 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 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Collections-C. If not, see . 19 | */ 20 | 21 | #include "array.h" 22 | #include "stack.h" 23 | 24 | 25 | struct stack_s { 26 | Array *v; 27 | 28 | void *(*mem_alloc) (size_t size); 29 | void *(*mem_calloc) (size_t blocks, size_t size); 30 | void (*mem_free) (void *block); 31 | }; 32 | 33 | 34 | /** 35 | * Initializes the fields of the StackConf struct to default values. 36 | * 37 | * @param[in, out] conf StackConf structure that is being initialized 38 | */ 39 | void stack_conf_init(StackConf *conf) 40 | { 41 | array_conf_init(conf); 42 | } 43 | 44 | /** 45 | * Creates a new empty stack and returns a status code. 46 | * 47 | * @param[out] out pointer to where the newly created Stack is to be stored 48 | * 49 | * @return CC_OK if the creation was successful, or CC_ERR_ALLOC if the 50 | * memory allocation for the new Stack structure failed. 51 | */ 52 | enum cc_stat stack_new(Stack **out) 53 | { 54 | StackConf conf; 55 | stack_conf_init(&conf); 56 | return stack_new_conf(&conf, out); 57 | } 58 | 59 | /** 60 | * Creates a new empty Stack based on the StackConf struct and returns a 61 | * status code. 62 | * 63 | * The stack is allocated using the allocators specified in the StackConf 64 | * struct. The allocation may fail if the underlying allocator fails. It may also 65 | * fail if the values of exp_factor and capacity in the StackConf do not meet 66 | * the following condition: exp_factor < (CC_MAX_ELEMENTS / capacity). 67 | * 68 | * @param[in] conf stack configuration structure 69 | * @param[out] out pointer to where the newly created Stack is to be stored 70 | * 71 | * @return CC_OK if the creation was successful, CC_ERR_INVALID_CAPACITY if 72 | * the above mentioned condition is not met, or CC_ERR_ALLOC if the memory 73 | * allocation for the new Stack structure failed. 74 | */ 75 | enum cc_stat stack_new_conf(StackConf const * const conf, Stack **out) 76 | { 77 | Stack *stack = conf->mem_calloc(1, sizeof(Stack)); 78 | 79 | if (!stack) 80 | return CC_ERR_ALLOC; 81 | 82 | stack->mem_alloc = conf->mem_alloc; 83 | stack->mem_calloc = conf->mem_calloc; 84 | stack->mem_free = conf->mem_free; 85 | 86 | Array *array; 87 | enum cc_stat status; 88 | if ((status = array_new_conf(conf, &array)) == CC_OK) { 89 | stack->v = array; 90 | } else { 91 | conf->mem_free(stack); 92 | return status; 93 | } 94 | *out = stack; 95 | return CC_OK; 96 | } 97 | 98 | /** 99 | * Destroys the specified stack structure, while leaving the data it holds 100 | * intact. 101 | * 102 | * @param[in] stack the Stack to be destroyed 103 | */ 104 | void stack_destroy(Stack *stack) 105 | { 106 | array_destroy(stack->v); 107 | stack->mem_free(stack); 108 | } 109 | 110 | /** 111 | * Destroys the specified stack structure along with all the data it holds. 112 | * 113 | * @note This function should not be called on a Stack that has some of its 114 | * elements allocated on the stack (stack memory). 115 | * 116 | * @param[in] stack the stack to be destroyed 117 | */ 118 | void stack_destroy_free(Stack *stack) 119 | { 120 | array_destroy_free(stack->v); 121 | free(stack); 122 | } 123 | 124 | /** 125 | * Pushes a new element onto the stack. 126 | * 127 | * @param[in] stack the stack on which the element is being pushed onto 128 | * @param[in] element the element being pushed onto the stack 129 | * 130 | * @return CC_OK if the element was successfully pushed, or CC_ERR_ALLOC 131 | * if the memory allocation for the new element failed. 132 | */ 133 | enum cc_stat stack_push(Stack *stack, void *element) 134 | { 135 | return array_add(stack->v, element); 136 | } 137 | 138 | /** 139 | * Gets the top element of the Stack without removing it and sets the out 140 | * parameter to its value. 141 | * 142 | * @param[in] stack the stack whose top element is being returned 143 | * @param[out] out pointer to where the returned value is stored 144 | * 145 | * @return CC_OK if the element was found, or CC_ERR_VALUE_NOT_FOUND if the 146 | * Stack is empty. 147 | */ 148 | enum cc_stat stack_peek(Stack *stack, void **out) 149 | { 150 | return array_get_last(stack->v, out); 151 | } 152 | 153 | /** 154 | * Pops (removes) the top element of the stack and optionally sets the out 155 | * parameter to the value of the popped element. 156 | * 157 | * @param[in] stack the stack whose top element is being popped 158 | * @param[out] out pointer to where the popped value is stored, or NULL if it is 159 | * to be ignored 160 | * 161 | * @return CC_OK if the element was successfully popped, or CC_ERR_OUT_OF_RANGE 162 | * if the Stack is already empty. 163 | */ 164 | enum cc_stat stack_pop(Stack *stack, void **out) 165 | { 166 | return array_remove_last(stack->v, out); 167 | } 168 | 169 | /** 170 | * Returns the number of Stack elements. 171 | * 172 | * @param[in] stack the Stack whose number of elements is being returned 173 | * 174 | * @return the number of Stack elements. 175 | */ 176 | size_t stack_size(Stack *stack) 177 | { 178 | return array_size(stack->v); 179 | } 180 | 181 | /** 182 | * Applies the function fn to each element of the Stack. 183 | * 184 | * @param[in] stack the Stack on which this operation being performed 185 | * @param[in] fn the operation function that is to be invoked on each 186 | * element of the Stack 187 | */ 188 | void stack_map(Stack *stack, void (*fn) (void *)) 189 | { 190 | array_map(stack->v, fn); 191 | } 192 | 193 | /** 194 | * Initializes the iterator. 195 | * 196 | * @param[in] iter the iterator that is being initialized 197 | * @param[in] s the stack to iterate over 198 | */ 199 | void stack_iter_init(StackIter *iter, Stack *s) 200 | { 201 | array_iter_init(&(iter->i), s->v); 202 | } 203 | 204 | /** 205 | * Advances the iterator and sets the out parameter to the value of the 206 | * next element in the sequence. 207 | * 208 | * @param[in] iter the iterator that is being advanced 209 | * @param[out] out pointer to where the next element is set 210 | * 211 | * @return CC_OK if the iterator was advanced, or CC_ITER_END if the 212 | * end of the Stack has been reached. 213 | */ 214 | enum cc_stat stack_iter_next(StackIter *iter, void **out) 215 | { 216 | return array_iter_next(&(iter->i), out); 217 | } 218 | 219 | /** 220 | * Replaces the last returned element by stack_iter_next() 221 | * with the specified element and optionally sets the out parameter to 222 | * the value of the replaced element. 223 | * 224 | * @note This function should only ever be called after a call to 225 | * stack_iter_next(). 226 | * 227 | * @param[in] iter the iterator on which this operation is being performed 228 | * @param[in] element the replacement element 229 | * @param[out] out pointer to where the replaced element is stored, or NULL 230 | * if it is to be ignored 231 | * 232 | * @return CC_OK if the element was replaced successfully, or 233 | * CC_ERR_OUT_OF_RANGE. 234 | */ 235 | enum cc_stat stack_iter_replace(StackIter *iter, void *element, void **out) 236 | { 237 | return array_iter_replace(&(iter->i), element, out); 238 | } 239 | 240 | /** 241 | * Initializes the zip iterator. 242 | * 243 | * @param[in] iter iterator that is being initialized 244 | * @param[in] s1 first Stack 245 | * @param[in] s2 second Stack 246 | */ 247 | void stack_zip_iter_init(StackZipIter *iter, Stack *s1, Stack *s2) 248 | { 249 | array_zip_iter_init(&(iter->i), s1->v, s2->v); 250 | } 251 | 252 | /** 253 | * Outputs the next element pair in the sequence and advances the iterator. 254 | * 255 | * @param[in] iter iterator that is being advanced 256 | * @param[out] out1 output of the first stack element 257 | * @param[out] out2 output of the second stack element 258 | * 259 | * @return CC_OK if a next element pair is returned, or CC_ITER_END if the end 260 | * of one of the stacks has been reached. 261 | */ 262 | enum cc_stat stack_zip_iter_next(StackZipIter *iter, void **out1, void **out2) 263 | { 264 | return array_zip_iter_next(&(iter->i), out1, out2); 265 | } 266 | 267 | /** 268 | * Replaces the last returned element pair by stack_zip_iter_next() 269 | * with the specified replacement element pair. 270 | * 271 | * @param[in] iter iterator on which this operation is being performed 272 | * @param[in] e1 first stack's replacement element 273 | * @param[in] e2 second stack's replacement element 274 | * @param[out] out1 output of the replaced element from the first stack 275 | * @param[out] out2 output of the replaced element from the second stack 276 | * 277 | * @return CC_OK if the element was successfully replaced, or CC_ERR_OUT_OF_RANGE. 278 | */ 279 | enum cc_stat stack_zip_iter_replace(StackZipIter *iter, void *e1, void *e2, void **out1, void **out2) 280 | { 281 | return array_zip_iter_replace(&(iter->i), e1, e2, out1, out2); 282 | } 283 | -------------------------------------------------------------------------------- /static test data/Collections-C/src/stack.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Collections-C 3 | * Copyright (C) 2013-2015 Srđan Panić 4 | * 5 | * This file is part of Collections-C. 6 | * 7 | * Collections-C is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * Collections-C 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 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Collections-C. If not, see . 19 | */ 20 | 21 | #ifndef COLLECTIONS_C_STACK_H 22 | #define COLLECTIONS_C_STACK_H 23 | 24 | #include "common.h" 25 | #include "array.h" 26 | 27 | /** 28 | * A LIFO (last in first out) structure. Supports constant time 29 | * insertion, removal and lookup. 30 | */ 31 | typedef struct stack_s Stack; 32 | 33 | /** 34 | * Stack configuration structrue. Used to initialize a new Stack 35 | * with specific attributes. 36 | */ 37 | typedef ArrayConf StackConf; 38 | 39 | /** 40 | * Stack iterator structure. Used to iterate over the elements of 41 | * the Stack in an ascending order. The iterator also supports 42 | * operations for safely adding and removing elements during 43 | * iteration. 44 | */ 45 | typedef struct stack_iter_s { 46 | ArrayIter i; 47 | } StackIter; 48 | 49 | /** 50 | * Stack zip iterator structure. Used to iterate over the elements 51 | * of two Stacks in lockstep in an ascending order until one of the 52 | * Stacks is exhausted. The iterator also supports operations for 53 | * safely adding and removing elements during iteration. 54 | */ 55 | typedef struct stack_zip_iter_s { 56 | ArrayZipIter i; 57 | } StackZipIter; 58 | 59 | 60 | void stack_conf_init (StackConf *conf); 61 | enum cc_stat stack_new (Stack **out); 62 | enum cc_stat stack_new_conf (StackConf const * const conf, Stack **out); 63 | void stack_destroy (Stack *stack); 64 | void stack_destroy_free (Stack *stack); 65 | 66 | enum cc_stat stack_push (Stack *stack, void *element); 67 | enum cc_stat stack_peek (Stack *stack, void **out); 68 | enum cc_stat stack_pop (Stack *stack, void **out); 69 | 70 | size_t stack_size (Stack *stack); 71 | void stack_map (Stack *stack, void (*fn) (void *)); 72 | 73 | void stack_iter_init (StackIter *iter, Stack *s); 74 | enum cc_stat stack_iter_next (StackIter *iter, void **out); 75 | enum cc_stat stack_iter_replace (StackIter *iter, void *element, void **out); 76 | 77 | void stack_zip_iter_init (StackZipIter *iter, Stack *a1, Stack *a2); 78 | enum cc_stat stack_zip_iter_next (StackZipIter *iter, void **out1, void **out2); 79 | enum cc_stat stack_zip_iter_replace(StackZipIter *iter, void *e1, void *e2, void **out1, void **out2); 80 | 81 | 82 | 83 | #endif /* COLLECTIONS_C_STACK_H */ 84 | -------------------------------------------------------------------------------- /static test data/Collections-C/src/treeset.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Collections-C 3 | * Copyright (C) 2013-2014 Srđan Panić 4 | * 5 | * This file is part of Collections-C. 6 | * 7 | * Collections-C is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * Collections-C 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 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Collections-C. If not, see . 19 | */ 20 | 21 | #include "treeset.h" 22 | 23 | struct treeset_s { 24 | TreeTable *t; 25 | int *dummy; 26 | 27 | void *(*mem_alloc) (size_t size); 28 | void *(*mem_calloc) (size_t blocks, size_t size); 29 | void (*mem_free) (void *block); 30 | }; 31 | 32 | /** 33 | * Initializes the fields of the TreeSetConf struct to default values. 34 | * 35 | * @param[in, out] conf the configuration struct that is being initialized 36 | */ 37 | void treeset_conf_init(TreeSetConf *conf) 38 | { 39 | treetable_conf_init(conf); 40 | } 41 | 42 | /** 43 | * Creates a new TreeSet and returns a status code. 44 | * 45 | * @param[in] cmp the comparator function used to order elements 46 | * @param[out] out pointer to where the newly created TreeSet is to be stored 47 | * 48 | * @return CC_OK if the creation was successful, or CC_ERR_ALLOC if the memory 49 | * allocation for the new TreeSet failed. 50 | */ 51 | enum cc_stat treeset_new(int (*cmp) (const void*, const void*), TreeSet **set) 52 | { 53 | TreeSetConf conf; 54 | treeset_conf_init(&conf); 55 | conf.cmp = cmp; 56 | return treeset_new_conf(&conf, set); 57 | } 58 | 59 | /** 60 | * Creates a new TreeSet based on the specified TreeSetConf struct and returns 61 | * a status code. 62 | * 63 | * The TreeSet is allocated using the allocators specified in the TreeSetConf 64 | * object. The allocation may fail if the underlying allocator fails. 65 | * 66 | * @param[in] conf TreeSet configuration struct. All fields must be initialized. 67 | * @param[out] out Pointer to where the newly created TreeSet is stored 68 | * 69 | * @return CC_OK if the creation was successful, or CC_ERR_ALLOC if the memory 70 | * allocation for the new TreeSet structure failed. 71 | */ 72 | enum cc_stat treeset_new_conf(TreeSetConf const * const conf, TreeSet **tset) 73 | { 74 | TreeSet *set = conf->mem_calloc(1, sizeof(TreeSet)); 75 | 76 | if (!set) 77 | return CC_ERR_ALLOC; 78 | 79 | TreeTable *table; 80 | enum cc_stat s = treetable_new_conf(conf, &table); 81 | 82 | if (s != CC_OK) { 83 | conf->mem_free(set); 84 | return s; 85 | } 86 | set->t = table; 87 | set->dummy = (int*) 1; 88 | set->mem_alloc = conf->mem_alloc; 89 | set->mem_calloc = conf->mem_calloc; 90 | set->mem_free = conf->mem_free; 91 | 92 | *tset = set; 93 | return CC_OK; 94 | } 95 | 96 | /** 97 | * Destroys the specified TreeSet. 98 | * 99 | * @param[in] set the TreeSet to be destroyed 100 | */ 101 | void treeset_destroy(TreeSet *set) 102 | { 103 | treetable_destroy(set->t); 104 | set->mem_free(set); 105 | } 106 | 107 | /** 108 | * Adds a new element to the set. 109 | * 110 | * @param[in] set the set to which the element is being added 111 | * @param[in] element the element being added 112 | * 113 | * @return CC_OK if the operation was successful, or CC_ERR_ALLOC if the 114 | * memory allocation for the new element failed. 115 | */ 116 | enum cc_stat treeset_add(TreeSet *set, void *element) 117 | { 118 | return treetable_add(set->t, element, set->dummy); 119 | } 120 | 121 | /** 122 | * Removes the specified element from the TreeSet and sets the out 123 | * parameter to its value. 124 | * 125 | * @param[in] set the set from which the element is being removed 126 | * @param[in] element the element being removed 127 | * @param[out] out pointer to where the removed value is stored, or NULL 128 | * if it is to be ignored 129 | * 130 | * @return CC_OK if the mapping was successfully removed, or CC_ERR_VALUE_NOT_FOUND 131 | * if the value was not found. 132 | */ 133 | enum cc_stat treeset_remove(TreeSet *set, void *element, void **out) 134 | { 135 | if (treetable_remove(set->t, element, out) == CC_ERR_KEY_NOT_FOUND) 136 | return CC_ERR_VALUE_NOT_FOUND; 137 | 138 | return CC_OK; 139 | } 140 | 141 | /** 142 | * Removes all elements from the specified set. 143 | * 144 | * @param set the set from which all elements are being removed 145 | */ 146 | void treeset_remove_all(TreeSet *set) 147 | { 148 | treetable_remove_all(set->t); 149 | } 150 | 151 | /** 152 | * Returns the first element of the set. 153 | * 154 | * @param[in] set the set from which the first element is being returned 155 | * @param[out] out pointer to where the returned element is stored 156 | * 157 | * @return CC_OK if the element was found, or CC_ERR_VALUE_NOT_FOUND if not. 158 | */ 159 | enum cc_stat treeset_get_first(TreeSet *set, void **out) 160 | { 161 | if (treetable_get_first_key(set->t, out) == CC_ERR_KEY_NOT_FOUND) 162 | return CC_ERR_VALUE_NOT_FOUND; 163 | 164 | return CC_OK; 165 | } 166 | 167 | /** 168 | * Returns the last (highest) element of the set. 169 | * 170 | * @param[in] set the set from which the last element is being returned 171 | * @param[out] out pointer to where the returned element is stored 172 | * 173 | * @return CC_OK if the element was found, or CC_ERR_VALUE_NOT_FOUND if not. 174 | */ 175 | enum cc_stat treeset_get_last(TreeSet *set, void **out) 176 | { 177 | if (treetable_get_last_key(set->t, out) == CC_ERR_KEY_NOT_FOUND) 178 | return CC_ERR_VALUE_NOT_FOUND; 179 | 180 | return CC_OK; 181 | } 182 | 183 | /** 184 | * Returns the immediate successor of the specified element. 185 | * 186 | * @param[in] set the set on which this operation is performed 187 | * @param[in] element the element whose successor is being returned 188 | * @param[out] out pointer to where the returned element is stored 189 | * 190 | * @return CC_OK if the element was found, or CC_ERR_VALUE_NOT_FOUND if not. 191 | */ 192 | enum cc_stat treeset_get_greater_than(TreeSet *set, void *element, void **out) 193 | { 194 | if (treetable_get_greater_than(set->t, element, out) == CC_ERR_KEY_NOT_FOUND) 195 | return CC_ERR_VALUE_NOT_FOUND; 196 | 197 | return CC_OK; 198 | } 199 | 200 | /** 201 | * Returns the immediate predecessor of the specified element. 202 | * 203 | * @param[in] set the set on which this operation is performed 204 | * @param[in] element the element whose predecessor is being returned 205 | * @param[out] out pointer to where the returned element is stored 206 | * 207 | * @return CC_OK if the element was found, or CC_ERR_VALUE_NOT_FOUND if not. 208 | */ 209 | enum cc_stat treeset_get_lesser_than(TreeSet *set, void *element, void **out) 210 | { 211 | if (treetable_get_lesser_than(set->t, element, out) == CC_ERR_KEY_NOT_FOUND) 212 | return CC_ERR_VALUE_NOT_FOUND; 213 | 214 | return CC_OK; 215 | } 216 | 217 | /** 218 | * Checks whether an element is a part of the specified set. 219 | * 220 | * @param[in] set the set being searched for the specified element 221 | * @param[in] element the element being searched for 222 | * 223 | * @return true if the specified element is an element of the set. 224 | */ 225 | bool treeset_contains(TreeSet *set, void *element) 226 | { 227 | return treetable_contains_key(set->t, element); 228 | } 229 | 230 | /** 231 | * Returns the size of the specified set. 232 | * 233 | * @param[in] set the set whose size is being returned 234 | * 235 | * @return the size of the set. 236 | */ 237 | size_t treeset_size(TreeSet *set) 238 | { 239 | return treetable_size(set->t); 240 | } 241 | 242 | /** 243 | * Applies the function fn to each element of the TreeSet. 244 | * 245 | * @param[in] set the set on which this operation is being performed 246 | * @param[in] fn the operation function that is invoked on each element 247 | * of the set 248 | */ 249 | void treeset_foreach(TreeSet *set, void (*fn) (const void*)) 250 | { 251 | treetable_foreach_key(set->t, fn); 252 | } 253 | 254 | /** 255 | * Initializes the set iterator. 256 | * 257 | * @param[in] iter the iterator that is being initialized 258 | * @param[in] set the set on which this iterator will operate 259 | */ 260 | void treeset_iter_init(TreeSetIter *iter, TreeSet *set) 261 | { 262 | treetable_iter_init(&(iter->i), set->t); 263 | } 264 | 265 | /** 266 | * Advances the iterator and sets the out parameter to the value of the 267 | * next element. 268 | * 269 | * @param[in] iter the iterator that is being advanced 270 | * @param[out] element pointer to where the next element is set 271 | * 272 | * @return CC_OK if the iterator was advanced, or CC_ITER_END if the 273 | * end of the TreeSet has been reached. 274 | */ 275 | enum cc_stat treeset_iter_next(TreeSetIter *iter, void **element) 276 | { 277 | TreeTableEntry entry; 278 | 279 | if (treetable_iter_next(&(iter->i), &entry) != CC_OK) 280 | return CC_ITER_END; 281 | 282 | *element = entry.key; 283 | return CC_OK; 284 | } 285 | 286 | /** 287 | * Removes the last returned element by treeset_iter_next() 288 | * function without invalidating the iterator and optionally sets the 289 | * out parameter to the value of the removed element. 290 | * 291 | * @note This Function should only ever be called after a call to 292 | * treeset_iter_next(). 293 | * 294 | * @param[in] iter the iterator on which this operation is performed 295 | * @param[out] out pointer to where the removed element is stored, or NULL 296 | * if it is to be ignored 297 | * 298 | * @return CC_OK if the element was successfully removed, or 299 | * CC_ERR_KEY_NOT_FOUND. 300 | */ 301 | enum cc_stat treeset_iter_remove(TreeSetIter *iter, void **out) 302 | { 303 | return treetable_iter_remove(&(iter->i), out); 304 | } 305 | -------------------------------------------------------------------------------- /static test data/Collections-C/src/treeset.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Collections-C 3 | * Copyright (C) 2013-2014 Srđan Panić 4 | * 5 | * This file is part of Collections-C. 6 | * 7 | * Collections-C is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * Collections-C 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 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Collections-C. If not, see . 19 | */ 20 | 21 | #ifndef COLLECTIONS_C_TREESET_H 22 | #define COLLECTIONS_C_TREESET_H 23 | 24 | #include "common.h" 25 | #include "treetable.h" 26 | 27 | /** 28 | * An ordered set. The lookup, deletion, and insertion are 29 | * performed in logarithmic time. 30 | */ 31 | typedef struct treeset_s TreeSet; 32 | 33 | /** 34 | * TreeSet configuration structure. 35 | */ 36 | typedef TreeTableConf TreeSetConf; 37 | 38 | /** 39 | * TreeSet iterator structure. Used to iterate over the elements of the set. 40 | * The iterator also supports operations for safely removing elements 41 | * during iteration. 42 | */ 43 | typedef struct treeset_iter_s { 44 | TreeTableIter i; 45 | } TreeSetIter; 46 | 47 | 48 | void treeset_conf_init (TreeSetConf *conf); 49 | enum cc_stat treeset_new (int (*cmp) (const void*, const void*), TreeSet **set); 50 | enum cc_stat treeset_new_conf (TreeSetConf const * const conf, TreeSet **set); 51 | 52 | void treeset_destroy (TreeSet *set); 53 | 54 | enum cc_stat treeset_add (TreeSet *set, void *element); 55 | enum cc_stat treeset_remove (TreeSet *set, void *element, void **out); 56 | void treeset_remove_all (TreeSet *set); 57 | 58 | enum cc_stat treeset_get_first (TreeSet *set, void **out); 59 | enum cc_stat treeset_get_last (TreeSet *set, void **out); 60 | enum cc_stat treeset_get_greater_than (TreeSet *set, void *element, void **out); 61 | enum cc_stat treeset_get_lesser_than (TreeSet *set, void *element, void **out); 62 | 63 | bool treeset_contains (TreeSet *set, void *element); 64 | size_t treeset_size (TreeSet *set); 65 | 66 | void treeset_foreach (TreeSet *set, void (*op) (const void*)); 67 | 68 | void treeset_iter_init (TreeSetIter *iter, TreeSet *set); 69 | enum cc_stat treeset_iter_next (TreeSetIter *iter, void **element); 70 | enum cc_stat treeset_iter_remove (TreeSetIter *iter, void **out); 71 | 72 | #endif /* COLLECTIONS_C_TREESET_H */ 73 | -------------------------------------------------------------------------------- /static test data/Collections-C/src/treetable.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Collections-C 3 | * Copyright (C) 2013-2015 Srđan Panić 4 | * 5 | * This file is part of Collections-C. 6 | * 7 | * Collections-C is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * Collections-C 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 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with Collections-C. If not, see . 19 | */ 20 | 21 | #ifndef COLLECTIONS_C_TREETABLE_H 22 | #define COLLECTIONS_C_TREETABLE_H 23 | 24 | #include "common.h" 25 | 26 | /** 27 | * An ordered key-value map. TreeTable supports logarithmic time 28 | * insertion, removal and lookup of values. 29 | */ 30 | typedef struct treetable_s TreeTable; 31 | 32 | /** 33 | * Red-Black tree node. 34 | * 35 | * @note Modifying this structure may invalidate the table. 36 | */ 37 | typedef struct rbnode_s { 38 | /** 39 | * Key in the table. */ 40 | void *key; 41 | 42 | /** 43 | * Value associated with the key */ 44 | void *value; 45 | 46 | /** 47 | * The color of this node */ 48 | char color; 49 | 50 | /** 51 | * Parent of this node */ 52 | struct rbnode_s *parent; 53 | 54 | /** 55 | * Left child node */ 56 | struct rbnode_s *left; 57 | 58 | /** 59 | * Right child node */ 60 | struct rbnode_s *right; 61 | } RBNode; 62 | 63 | /** 64 | * TreeTable table entry. 65 | */ 66 | typedef struct tree_table_entry_s { 67 | void *key; 68 | void *value; 69 | } TreeTableEntry; 70 | 71 | /** 72 | * TreeTable iterator structure. Used to iterate over the entries 73 | * of the table. The iterator also supports operations for safely 74 | * removing elements during iteration. 75 | * 76 | * @note This structure should only be modified through the 77 | * iterator functions. 78 | */ 79 | typedef struct tree_table_iter_s { 80 | TreeTable *table; 81 | RBNode *current; 82 | RBNode *next; 83 | } TreeTableIter; 84 | 85 | /** 86 | * TreeTable configuration structure. Used to initialize a new 87 | * TreeTable with specific attributes. 88 | */ 89 | typedef struct treetable_conf_s { 90 | int (*cmp) (const void *k1, const void *k2); 91 | void *(*mem_alloc) (size_t size); 92 | void *(*mem_calloc) (size_t blocks, size_t size); 93 | void (*mem_free) (void *block); 94 | } TreeTableConf; 95 | 96 | 97 | void treetable_conf_init (TreeTableConf *conf); 98 | enum cc_stat treetable_new (int (*cmp) (const void*, const void*), TreeTable **tt); 99 | enum cc_stat treetable_new_conf (TreeTableConf const * const conf, TreeTable **tt); 100 | 101 | void treetable_destroy (TreeTable *table); 102 | enum cc_stat treetable_add (TreeTable *table, void *key, void *val); 103 | 104 | enum cc_stat treetable_remove (TreeTable *table, void *key, void **out); 105 | void treetable_remove_all (TreeTable *table); 106 | enum cc_stat treetable_remove_first (TreeTable *table, void **out); 107 | enum cc_stat treetable_remove_last (TreeTable *table, void **out); 108 | 109 | enum cc_stat treetable_get (TreeTable const * const table, const void *key, void **out); 110 | enum cc_stat treetable_get_first_value (TreeTable const * const table, void **out); 111 | enum cc_stat treetable_get_first_key (TreeTable const * const table, void **out); 112 | enum cc_stat treetable_get_last_value (TreeTable const * const table, void **out); 113 | enum cc_stat treetable_get_last_key (TreeTable const * const table, void **out); 114 | enum cc_stat treetable_get_greater_than (TreeTable const * const table, const void *key, void **out); 115 | enum cc_stat treetable_get_lesser_than (TreeTable const * const table, const void *key, void **out); 116 | 117 | size_t treetable_size (TreeTable const * const table); 118 | bool treetable_contains_key (TreeTable const * const table, const void *key); 119 | size_t treetable_contains_value (TreeTable const * const table, const void *value); 120 | 121 | void treetable_foreach_key (TreeTable *table, void (*op) (const void*)); 122 | void treetable_foreach_value (TreeTable *table, void (*op) (void*)); 123 | 124 | void treetable_iter_init (TreeTableIter *iter, TreeTable *table); 125 | enum cc_stat treetable_iter_next (TreeTableIter *iter, TreeTableEntry *entry); 126 | enum cc_stat treetable_iter_remove (TreeTableIter *iter, void **out); 127 | 128 | #ifdef DEBUG 129 | #define RB_ERROR_CONSECUTIVE_RED 0 130 | #define RB_ERROR_BLACK_HEIGHT 1 131 | #define RB_ERROR_TREE_STRUCTURE 2 132 | #define RB_ERROR_OK 4 133 | 134 | int treetable_assert_rb_rules(TreeTable *table); 135 | #endif /* DEBUG */ 136 | 137 | #endif /* COLLECTIONS_C_TREETABLE_H */ 138 | -------------------------------------------------------------------------------- /static test data/Collections-C/test/Makefile.am: -------------------------------------------------------------------------------- 1 | check_PROGRAMS = \ 2 | list_test \ 3 | hashtable_test \ 4 | array_test \ 5 | slist_test \ 6 | deque_test \ 7 | hashset_test \ 8 | stack_test \ 9 | queue_test \ 10 | treetable_test \ 11 | treeset_test 12 | 13 | TESTS = \ 14 | list_test \ 15 | hashtable_test \ 16 | array_test \ 17 | slist_test \ 18 | deque_test \ 19 | hashset_test \ 20 | stack_test \ 21 | queue_test \ 22 | treetable_test \ 23 | treeset_test 24 | 25 | list_test_LDFLAGS = -static 26 | hashtable_test_LDFLAGS = -static 27 | array_test_LDFLAGS = -static 28 | slist_test_LDFLAGS = -static 29 | deque_test_LDFLAGS = -static 30 | hashset_test_LDFLAGS = -static 31 | stack_test_LDFLAGS = -static 32 | queue_test_LDFLAGS = -static 33 | treetable_test_LDFLAGS = -static 34 | treeset_test_LDFLAGS = -static 35 | 36 | treetable_test_CFLAGS = -DDEBUG -g -O0 -Werror -std=c99 37 | list_test_CFLAGS = -DDEBUG -g -O0 -Werror -std=c99 38 | hashtable_test_CFLAGS = -DDEBUG -g -O0 -Werror -std=c99 39 | array_test_CFLAGS = -DDEBUG -g -O0 -Werror -std=c99 40 | slist_test_CFLAGS = -DDEBUG -g -O0 -Werror -std=c99 41 | deque_test_CFLAGS = -DDEBUG -g -O0 -Werror -std=c99 42 | hashset_test_CFLAGS = -DDEBUG -g -O0 -Werror -std=c99 43 | stack_test_CFLAGS = -DDEBUG -g -O0 -Werror -std=c99 44 | queue_test_CFLAGS = -DDEBUG -g -O0 -Werror -std=c99 45 | treeset_test_CFLAGS = -DDEBUG -g -O0 -Werror -std=c99 46 | 47 | treeset_test_SOURCES =\ 48 | treeset_test.c\ 49 | ../src/common.h \ 50 | ../src/common.c \ 51 | ../src/treeset.c\ 52 | ../src/treeset.h\ 53 | ../src/treetable.c\ 54 | ../src/treetable.h\ 55 | test.c\ 56 | test.h 57 | 58 | list_test_SOURCES =\ 59 | list_test.c \ 60 | ../src/common.h \ 61 | ../src/common.c \ 62 | ../src/list.c \ 63 | ../src/list.h \ 64 | test.c \ 65 | test.h 66 | 67 | hashtable_test_SOURCES =\ 68 | hashtable_test.c \ 69 | ../src/common.h \ 70 | ../src/common.c \ 71 | ../src/hashtable.c \ 72 | ../src/hashtable.h \ 73 | ../src/array.c \ 74 | ../src/array.h \ 75 | test.c \ 76 | test.h 77 | 78 | array_test_SOURCES =\ 79 | array_test.c\ 80 | ../src/common.h \ 81 | ../src/common.c \ 82 | ../src/array.c\ 83 | ../src/array.h\ 84 | test.c\ 85 | test.h 86 | 87 | slist_test_SOURCES =\ 88 | ../src/common.h \ 89 | ../src/common.c \ 90 | slist_test.c\ 91 | test.h\ 92 | test.c\ 93 | ../src/slist.h\ 94 | ../src/slist.c 95 | 96 | deque_test_SOURCES =\ 97 | ../src/common.h \ 98 | ../src/common.c \ 99 | deque_test.c\ 100 | test.h test.c\ 101 | ../src/deque.c\ 102 | ../src/deque.h 103 | 104 | hashset_test_SOURCES =\ 105 | hashset_test.c\ 106 | test.h\ 107 | test.c\ 108 | ../src/common.c \ 109 | ../src/common.h \ 110 | ../src/hashset.c\ 111 | ../src/hashset.h\ 112 | ../src/hashtable.h\ 113 | ../src/hashtable.c\ 114 | ../src/array.c\ 115 | ../src/array.h 116 | 117 | stack_test_SOURCES =\ 118 | stack_test.c\ 119 | test.h\ 120 | test.c\ 121 | ../src/common.h \ 122 | ../src/common.c \ 123 | ../src/stack.c\ 124 | ../src/stack.h\ 125 | ../src/array.c\ 126 | ../src/array.h 127 | 128 | queue_test_SOURCES =\ 129 | queue_test.c\ 130 | test.h\ 131 | test.c\ 132 | ../src/common.h \ 133 | ../src/common.c \ 134 | ../src/queue.c\ 135 | ../src/queue.h\ 136 | ../src/deque.c\ 137 | ../src/deque.h 138 | 139 | treetable_test_SOURCES =\ 140 | treetable_test.c\ 141 | test.c\ 142 | test.h\ 143 | ../src/common.h \ 144 | ../src/common.c \ 145 | ../src/treetable.c\ 146 | ../src/treetable.h\ 147 | ../src/deque.h\ 148 | ../src/deque.c 149 | -------------------------------------------------------------------------------- /static test data/Collections-C/test/hashset_test.c: -------------------------------------------------------------------------------- 1 | #include "../src/hashset.h" 2 | #include "test.h" 3 | #include 4 | 5 | void test_hashset_new(); 6 | void test_hashset_add(); 7 | void test_hashset_remove(); 8 | void test_hashset_remove_all(); 9 | void test_hashset_iter(); 10 | 11 | int main(int argc, char **argv) 12 | { 13 | cc_set_exit_on_failure(false); 14 | 15 | test_hashset_new(); 16 | test_hashset_add(); 17 | test_hashset_remove(); 18 | test_hashset_remove_all(); 19 | test_hashset_iter(); 20 | 21 | return cc_get_status(); 22 | } 23 | 24 | void test_hashset_new() 25 | { 26 | HashSetConf conf; 27 | hashset_conf_init(&conf); 28 | conf.initial_capacity = 7; 29 | 30 | HashSet *set; 31 | hashset_new_conf(&conf, &set); 32 | 33 | cc_assert(hashset_size(set) == 0, 34 | cc_msg("hashset_new: Initial size not 0")); 35 | 36 | size_t capacity = hashset_capacity(set); 37 | 38 | /* power of 2 rounding */ 39 | cc_assert(capacity == 8, 40 | cc_msg("hashset_new: Expected capactity was 8, but got %d", 41 | capacity)); 42 | 43 | hashset_destroy(set); 44 | } 45 | 46 | void test_hashset_add() 47 | { 48 | HashSet *hs; 49 | hashset_new(&hs); 50 | 51 | char *a = "foo"; 52 | char *b = "bar"; 53 | char *c = "baz"; 54 | char *d = "foo"; 55 | 56 | hashset_add(hs, a); 57 | hashset_add(hs, b); 58 | hashset_add(hs, c); 59 | hashset_add(hs, d); 60 | 61 | size_t size = hashset_size(hs); 62 | 63 | cc_assert(size == 3, 64 | cc_msg("hashset_add: Expected size was 3, but got %d", 65 | size)); 66 | 67 | cc_assert(hashset_contains(hs, a) && 68 | hashset_contains(hs, d), 69 | cc_msg("hashset_add: HashSet expected to contain elemnts" 70 | " %s and %s", a, d)); 71 | 72 | hashset_destroy(hs); 73 | } 74 | 75 | 76 | void test_hashset_remove() 77 | { 78 | HashSet *hs; 79 | hashset_new(&hs); 80 | 81 | char *a = "foo"; 82 | char *b = "bar"; 83 | char *c = "baz"; 84 | char *d = "foo"; 85 | 86 | hashset_add(hs, a); 87 | hashset_add(hs, b); 88 | hashset_add(hs, c); 89 | hashset_add(hs, d); 90 | 91 | hashset_remove(hs, "bar", NULL); 92 | 93 | size_t size = hashset_size(hs); 94 | 95 | cc_assert(size == 2, 96 | cc_msg("hashset_add: Expected size was 2, but got %d", 97 | size)); 98 | 99 | cc_assert(!hashset_contains(hs, "bar"), 100 | cc_msg("hashset_add: HashSet not expected to contain " 101 | "element %s", "foo")); 102 | 103 | hashset_destroy(hs); 104 | } 105 | 106 | 107 | void test_hashset_remove_all() 108 | { 109 | HashSet *hs; 110 | hashset_new(&hs); 111 | 112 | char *a = "foo"; 113 | char *b = "bar"; 114 | char *c = "baz"; 115 | char *d = "foo"; 116 | 117 | hashset_add(hs, a); 118 | hashset_add(hs, b); 119 | hashset_add(hs, c); 120 | hashset_add(hs, d); 121 | 122 | hashset_remove_all(hs); 123 | 124 | size_t size = hashset_size(hs); 125 | 126 | cc_assert(size == 0, 127 | cc_msg("hashset_add: Expected size was 0, but got %d", 128 | size)); 129 | 130 | cc_assert(!hashset_contains(hs, "bar") && 131 | !hashset_contains(hs, c), 132 | cc_msg("hashset_add: HashSet not empty after removing" 133 | " all elements")); 134 | 135 | hashset_destroy(hs); 136 | } 137 | 138 | void test_hashset_iter_next() 139 | { 140 | HashSet *hs; 141 | hashset_new(&hs); 142 | 143 | char *a = "foo"; 144 | char *b = "bar"; 145 | char *c = "baz"; 146 | 147 | hashset_add(hs, a); 148 | hashset_add(hs, b); 149 | hashset_add(hs, c); 150 | 151 | size_t x = 0; 152 | size_t y = 0; 153 | size_t z = 0; 154 | 155 | HashSetIter iter; 156 | hashset_iter_init(&iter, hs); 157 | 158 | char *e; 159 | while (hashset_iter_next(&iter, (void*)&e) != CC_ITER_END) { 160 | if (!strcmp(e, "foo")) 161 | x++; 162 | 163 | if (!strcmp(e, "bar")) 164 | y++; 165 | 166 | if (!strcmp(e, "baz")) 167 | z++; 168 | } 169 | 170 | cc_assert((x == 1) && (y == 1) && (z == 1), 171 | cc_msg("hashset_iter: Unexpected number of " 172 | "elements returned by the iterator")); 173 | 174 | hashset_destroy(hs); 175 | } 176 | 177 | void test_hashset_iter_remove() 178 | { 179 | HashSet *hs; 180 | hashset_new(&hs); 181 | 182 | char *a = "foo"; 183 | char *b = "bar"; 184 | char *c = "baz"; 185 | 186 | hashset_add(hs, a); 187 | hashset_add(hs, b); 188 | hashset_add(hs, c); 189 | 190 | HashSetIter iter; 191 | hashset_iter_init(&iter, hs); 192 | 193 | char *e; 194 | while (hashset_iter_next(&iter, (void*) &e) != CC_ITER_END) { 195 | if (!strcmp(e, "bar")) 196 | hashset_iter_remove(&iter, NULL); 197 | } 198 | 199 | cc_assert(hashset_size(hs) == 2, 200 | cc_msg("hashset_iter: Expected size 2 but got %d ", 201 | hashset_size(hs))); 202 | 203 | cc_assert(!hashset_contains(hs, "bar"), 204 | cc_msg("hashset_iter: Element (%s) still pressent " 205 | "after removal", "bar")); 206 | 207 | hashset_destroy(hs); 208 | } 209 | 210 | void test_hashset_iter() 211 | { 212 | test_hashset_iter_next(); 213 | test_hashset_iter_remove(); 214 | } 215 | -------------------------------------------------------------------------------- /static test data/Collections-C/test/hashtable_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "../src/hashtable.h" 4 | #include "test.h" 5 | #include 6 | 7 | static HashTableConf conf; 8 | 9 | void test_hashtable_new(); 10 | void test_hashtable_add(); 11 | void test_hashtable_remove(); 12 | void test_hashtable_get(); 13 | void test_hashtable_size(); 14 | void test_hashtable_remove_all(); 15 | void test_hashtable_capacity(); 16 | void test_hashtable_contains_key(); 17 | void test_hashtable_memory_chunks_as_keys(); 18 | void test_hashtable_iter_next(); 19 | void test_hashtable_iter_remove(); 20 | 21 | /* a dummy hash function used to force collisions */ 22 | static size_t collision_hash(const void *k, int l, uint32_t s) 23 | { 24 | return 1; 25 | } 26 | 27 | 28 | int main(int argc, char **argv) 29 | { 30 | cc_set_exit_on_failure(false); 31 | 32 | hashtable_conf_init(&conf); 33 | 34 | test_hashtable_new(); 35 | test_hashtable_size(); 36 | test_hashtable_remove_all(); 37 | test_hashtable_add(); 38 | test_hashtable_remove(); 39 | test_hashtable_get(); 40 | test_hashtable_capacity(); 41 | test_hashtable_contains_key(); 42 | test_hashtable_memory_chunks_as_keys(); 43 | test_hashtable_iter_next(); 44 | test_hashtable_iter_remove(); 45 | 46 | return cc_get_status(); 47 | } 48 | 49 | 50 | void test_hashtable_new() 51 | { 52 | hashtable_conf_init(&conf); 53 | conf.initial_capacity = 7; 54 | 55 | HashTable *table; 56 | hashtable_new_conf(&conf, &table); 57 | 58 | cc_assert(hashtable_size(table) == 0, 59 | cc_msg("hashtable_new: Initial size not 0")); 60 | 61 | size_t capacity = hashtable_capacity(table); 62 | 63 | /* power of 2 rounding */ 64 | cc_assert(capacity == 8, 65 | cc_msg("hashtable_new: Expected capactity was 8, but got %d", 66 | capacity)); 67 | 68 | hashtable_destroy(table); 69 | } 70 | 71 | void test_hashtable_add() 72 | { 73 | HashTable *table; 74 | hashtable_new(&table); 75 | 76 | char *a = "value"; 77 | char *b = "cookies"; 78 | char *c = "m31"; 79 | 80 | hashtable_add(table, "key", a); 81 | hashtable_add(table, "randomstring", b); 82 | hashtable_add(table, "5", c); 83 | 84 | size_t size = hashtable_size(table); 85 | 86 | cc_assert(size == 3, 87 | cc_msg("hashtable_add: Expected size was 3, but got %d", size)); 88 | 89 | char *r; 90 | hashtable_get(table, "key", (void*) &r); 91 | 92 | cc_assert(r == a, 93 | cc_msg("hashtable_add: Wrong value retrieved")); 94 | 95 | hashtable_destroy(table); 96 | 97 | /* 98 | * test collision handling 99 | */ 100 | hashtable_conf_init(&conf); 101 | conf.hash = collision_hash; 102 | 103 | hashtable_new_conf(&conf, &table); 104 | 105 | hashtable_add(table, "key", a); 106 | hashtable_add(table, "randomstring", c); 107 | 108 | size = hashtable_size(table); 109 | 110 | cc_assert(size == 2, 111 | cc_msg("hashtable_add: Expected size was 2, but got %d", size)); 112 | 113 | hashtable_get(table, "randomstring", (void*) &r); 114 | 115 | cc_assert(r == c, 116 | cc_msg("hashtable_add: Expected 'm31' to be retrieved, but got %s", c)); 117 | 118 | hashtable_destroy(table); 119 | } 120 | 121 | 122 | void test_hashtable_remove() 123 | { 124 | HashTable *table; 125 | hashtable_new(&table); 126 | 127 | char *a = "value"; 128 | char *b = "cookies"; 129 | char *c = "m31"; 130 | 131 | hashtable_add(table, "key", a); 132 | hashtable_add(table, "randomstring", b); 133 | hashtable_add(table, "5", c); 134 | 135 | char *rm; 136 | hashtable_remove(table, "randomstring", (void*) &rm); 137 | size_t size = hashtable_size(table); 138 | 139 | cc_assert(size == 2, 140 | cc_msg("hashtable_remove: Expected size was 2, but got %d", 141 | size)); 142 | 143 | char *g; 144 | int stat = hashtable_get(table, "randomstring", (void*) &g); 145 | 146 | cc_assert(stat == CC_ERR_KEY_NOT_FOUND, 147 | cc_msg("hashtable_remove: 'randomstring' key" 148 | " still mapped after removal")); 149 | 150 | hashtable_destroy(table); 151 | 152 | /* 153 | * test collision handling 154 | */ 155 | hashtable_conf_init(&conf); 156 | conf.hash = collision_hash; 157 | 158 | hashtable_new_conf(&conf, &table); 159 | 160 | hashtable_add(table, "key", a); 161 | hashtable_add(table, "randomstring", c); 162 | hashtable_add(table, "5", c); 163 | 164 | hashtable_remove(table, "randomstring", (void*) &rm); 165 | size = hashtable_size(table); 166 | 167 | cc_assert(size == 2, 168 | cc_msg("hashtable_remove: Expected size was 2, but got %d", 169 | size)); 170 | 171 | stat = hashtable_get(table, "randomstring", (void*) &g); 172 | 173 | cc_assert(stat == CC_ERR_KEY_NOT_FOUND, 174 | cc_msg("hashtable_remove: Expected 'm31' to" 175 | " be retrieved, but got %s", c)); 176 | 177 | hashtable_destroy(table); 178 | } 179 | 180 | 181 | void test_hashtable_remove_all() 182 | { 183 | HashTable *table; 184 | hashtable_new(&table); 185 | 186 | hashtable_add(table, "key", "value"); 187 | hashtable_add(table, "randomkey", "randomvalue"); 188 | 189 | hashtable_remove_all(table); 190 | size_t size = hashtable_size(table); 191 | 192 | cc_assert(size == 0, 193 | cc_msg("hashtable_remove_all: Table size %d," 194 | " when it should be 0", 195 | size)); 196 | 197 | char *g; 198 | int stat = hashtable_get(table, "key", (void*) &g); 199 | 200 | cc_assert(stat == CC_ERR_KEY_NOT_FOUND, 201 | cc_msg("hashtable_refmove_all: Value still" 202 | " accecible after removal")); 203 | 204 | hashtable_destroy(table); 205 | } 206 | 207 | 208 | void test_hashtable_get() 209 | { 210 | HashTable *table; 211 | hashtable_new(&table); 212 | 213 | char *val = "567"; 214 | 215 | hashtable_add(table, "key", "value"); 216 | hashtable_add(table, "123", val); 217 | 218 | char *ret; 219 | hashtable_get(table, "123", (void*) &ret); 220 | 221 | cc_assert(ret == val, 222 | cc_msg("hashtable_get: Incorrect value returned." 223 | " Expected %s, but got %s", val, ret)); 224 | 225 | hashtable_destroy(table); 226 | } 227 | 228 | 229 | void test_hashtable_size() 230 | { 231 | HashTable *table; 232 | hashtable_new(&table); 233 | 234 | hashtable_add(table, "key", "value"); 235 | hashtable_add(table, "randomstring", "cookies"); 236 | hashtable_add(table, "5", "asdf"); 237 | 238 | size_t size = hashtable_size(table); 239 | 240 | cc_assert(size == 3, 241 | cc_msg("hashtable_size: Expected size was 3, but got %d", 242 | size)); 243 | 244 | hashtable_destroy(table); 245 | } 246 | 247 | 248 | void test_hashtable_capacity() 249 | { 250 | hashtable_conf_init(&conf); 251 | 252 | conf.load_factor = 0.5f; 253 | conf.initial_capacity = 2; 254 | 255 | HashTable *t; 256 | hashtable_new_conf(&conf, &t); 257 | 258 | hashtable_add(t, "a", NULL); 259 | 260 | cc_assert(hashtable_capacity(t) == 2, 261 | cc_msg("hashtable_capacity: Expected capacity was 4, but got %d", 262 | hashtable_capacity(t))); 263 | 264 | hashtable_add(t, "b", NULL); 265 | 266 | cc_assert(hashtable_capacity(t) == 4, 267 | cc_msg("hashtable_capacity: Expected capacity was 8, but got %d", 268 | hashtable_capacity(t))); 269 | 270 | hashtable_add(t, "c", NULL); 271 | hashtable_add(t, "d", NULL); 272 | 273 | cc_assert(hashtable_capacity(t) == 8, 274 | cc_msg("hashtable_capacity: Expected capacity was 16, but got %d", 275 | hashtable_capacity(t))); 276 | 277 | hashtable_destroy(t); 278 | } 279 | 280 | 281 | void test_hashtable_contains_key() 282 | { 283 | HashTable *table; 284 | hashtable_new(&table); 285 | 286 | hashtable_add(table, "key", "value"); 287 | hashtable_add(table, "randomstring", "cookies"); 288 | hashtable_add(table, "5", "m31"); 289 | 290 | cc_assert(hashtable_contains_key(table, "key"), 291 | cc_msg("hashtable_contains_key: " 292 | "Key expected to be present, but isn't")); 293 | 294 | hashtable_remove(table, "key", NULL); 295 | 296 | cc_assert(!hashtable_contains_key(table, "key"), 297 | cc_msg("hashtable_contains_key:" 298 | " Key not expected to exist")); 299 | 300 | hashtable_destroy(table); 301 | } 302 | 303 | int cmp_k(const void *k1, const void *k2) 304 | { 305 | char *key1 = (char*) k1; 306 | char *key2 = (char*) k2; 307 | int i; 308 | for (i = 0; i < (sizeof(int) * 7); i++) { 309 | if (*key1 != *key2) 310 | return 1; 311 | key1++; 312 | key2++; 313 | } 314 | return 0; 315 | } 316 | 317 | void test_hashtable_memory_chunks_as_keys() 318 | { 319 | int array1[] = {1,2,3,4,5,6,7}; 320 | int array2[] = {34,1,4,1111,456,234,0}; 321 | int array3[] = {0,9,8,7,6,5,4}; 322 | 323 | hashtable_conf_init(&conf); 324 | 325 | conf.hash = GENERAL_HASH; 326 | conf.key_length = sizeof(int) * 7; 327 | conf.key_compare = cmp_k; 328 | 329 | HashTable *t; 330 | hashtable_new_conf(&conf, &t); 331 | 332 | hashtable_add(t, array1, "one"); 333 | hashtable_add(t, array2, "two"); 334 | hashtable_add(t, array3, "three"); 335 | 336 | char *a; 337 | char *b; 338 | 339 | hashtable_get(t, array1, (void*) &a); 340 | hashtable_get(t, array3, (void*) &b); 341 | 342 | cc_assert(strcmp(a, "one") == 0, 343 | cc_msg("hashtable_memory_chunks_as_keys: " 344 | "Expected value 'one', but got %s", 345 | a)); 346 | 347 | cc_assert(strcmp(b, "three") == 0, 348 | cc_msg("hashtable_key_test:" 349 | " Expected value 'three', but got %s", 350 | b)); 351 | 352 | hashtable_destroy(t); 353 | } 354 | 355 | void test_hashtable_iter_next() 356 | { 357 | HashTable *t; 358 | hashtable_new(&t); 359 | 360 | hashtable_add(t, "one", "1"); 361 | hashtable_add(t, "two", "2"); 362 | hashtable_add(t, "three", "3"); 363 | hashtable_add(t, "four", "4"); 364 | hashtable_add(t, "five", "5"); 365 | 366 | int one = 0; 367 | int two = 0; 368 | int three = 0; 369 | int four = 0; 370 | int five = 0; 371 | 372 | HashTableIter iter; 373 | hashtable_iter_init(&iter, t); 374 | 375 | TableEntry *entry; 376 | while (hashtable_iter_next(&iter, &entry) != CC_ITER_END) { 377 | char const *key = entry->key; 378 | 379 | if (!strcmp(key, "one")) 380 | one++; 381 | 382 | if (!strcmp(key, "two")) 383 | two++; 384 | 385 | if (!strcmp(key, "three")) 386 | three++; 387 | 388 | if (!strcmp(key, "four")) 389 | four++; 390 | 391 | if (!strcmp(key, "five")) 392 | five++; 393 | } 394 | 395 | bool asrt = (one == 1) && (two == 1) && 396 | (three == 1) && (four == 1) && 397 | (five == 1); 398 | 399 | cc_assert(asrt, 400 | cc_msg("hashtable_iter_next: Unexpected number" 401 | " of entries returned")); 402 | 403 | hashtable_destroy(t); 404 | } 405 | 406 | 407 | void test_hashtable_iter_remove() 408 | { 409 | HashTable *t; 410 | hashtable_new(&t); 411 | 412 | char *a = "foo"; 413 | char *b = "bar"; 414 | char *c = "baz"; 415 | 416 | hashtable_add(t, a, "a"); 417 | hashtable_add(t, b, "a"); 418 | hashtable_add(t, c, "a"); 419 | 420 | HashTableIter iter; 421 | hashtable_iter_init(&iter, t); 422 | 423 | TableEntry *entry; 424 | while (hashtable_iter_next(&iter, &entry) != CC_ITER_END) { 425 | char const *key = entry->key; 426 | 427 | if (!strcmp(key, "bar")) 428 | hashtable_iter_remove(&iter, NULL); 429 | } 430 | 431 | cc_assert(hashtable_size(t) == 2, 432 | cc_msg("hashtable_iter_remove: Expected size 2 but got %d ", 433 | hashtable_size(t))); 434 | 435 | cc_assert(!hashtable_contains_key(t, "bar"), 436 | cc_msg("hastable_iter_remove: Element (%s) still pressent " 437 | "after removal", "bar")); 438 | 439 | hashtable_destroy(t); 440 | } 441 | -------------------------------------------------------------------------------- /static test data/Collections-C/test/queue_test.c: -------------------------------------------------------------------------------- 1 | #include "../src/queue.h" 2 | #include "test.h" 3 | 4 | void test_queue_poll(); 5 | void test_queue_enqueue(); 6 | void test_queue_iter(); 7 | void test_queue_zip_iter(); 8 | 9 | 10 | int main(int argc, char **argv) 11 | { 12 | cc_set_exit_on_failure(false); 13 | 14 | test_queue_poll(); 15 | test_queue_enqueue(); 16 | test_queue_iter(); 17 | test_queue_zip_iter(); 18 | 19 | return cc_get_status(); 20 | } 21 | 22 | 23 | void test_queue_enqueue() 24 | { 25 | Queue *q; 26 | queue_new(&q); 27 | 28 | int a = 1; 29 | int b = 2; 30 | int c = 3; 31 | 32 | queue_enqueue(q, &a); 33 | queue_enqueue(q, &b); 34 | 35 | cc_assert(queue_size(q) == 2, 36 | cc_msg("queue_enqueue: Qeueu size not as expected")); 37 | 38 | 39 | void *p; 40 | queue_peek(q, &p); 41 | cc_assert(p == &a, 42 | cc_msg("queue_enqueue: Front element not as expected.")); 43 | 44 | queue_enqueue(q, &c); 45 | 46 | queue_peek(q, &p); 47 | cc_assert(p == &a, 48 | cc_msg("queue_enqueue: Front element not as expected.")); 49 | 50 | queue_destroy(q); 51 | } 52 | 53 | void test_queue_poll() 54 | { 55 | Queue *q; 56 | queue_new(&q); 57 | 58 | int a = 1; 59 | int b = 2; 60 | int c = 3; 61 | 62 | queue_enqueue(q, &a); 63 | queue_enqueue(q, &b); 64 | queue_enqueue(q, &c); 65 | 66 | void *p; 67 | 68 | queue_poll(q, &p); 69 | cc_assert(p == &a, 70 | cc_msg("queue_peek: Front element not as expected.")); 71 | 72 | queue_peek(q, &p); 73 | cc_assert(p == &b, 74 | cc_msg("queue_peek: Front element not as expected.")); 75 | 76 | queue_poll(q, &p); 77 | cc_assert(p == &b, 78 | cc_msg("queue_peek: Front element not as expected.")); 79 | 80 | queue_peek(q, &p); 81 | cc_assert(p == &c, 82 | cc_msg("queue_peek: Front element not as expected.")); 83 | 84 | queue_destroy(q); 85 | } 86 | 87 | void test_queue_iter() 88 | { 89 | Queue *q; 90 | queue_new(&q); 91 | 92 | int a = 1; 93 | int b = 2; 94 | int c = 3; 95 | 96 | queue_enqueue(q, &a); 97 | queue_enqueue(q, &b); 98 | queue_enqueue(q, &c); 99 | 100 | size_t x = 0; 101 | size_t y = 0; 102 | size_t z = 0; 103 | 104 | QueueIter iter; 105 | queue_iter_init(&iter, q); 106 | 107 | int *e; 108 | while (queue_iter_next(&iter, (void*) &e) != CC_ITER_END) { 109 | if (e == &a) 110 | x++; 111 | 112 | if (e == &b) 113 | y++; 114 | 115 | if (e == &c) 116 | z++; 117 | } 118 | 119 | cc_assert(x == 1 && y == 1 && z == 1, 120 | cc_msg("queue_iter: Unexpected number of elments returned " 121 | "by the iterator.")); 122 | 123 | queue_destroy(q); 124 | } 125 | 126 | 127 | void test_queue_zip_iter_next() 128 | { 129 | Queue *q1; 130 | queue_new(&q1); 131 | 132 | queue_enqueue(q1, "a"); 133 | queue_enqueue(q1, "b"); 134 | queue_enqueue(q1, "c"); 135 | queue_enqueue(q1, "d"); 136 | 137 | Queue *q2; 138 | queue_new(&q2); 139 | 140 | queue_enqueue(q2, "e"); 141 | queue_enqueue(q2, "f"); 142 | queue_enqueue(q2, "g"); 143 | 144 | QueueZipIter zip; 145 | queue_zip_iter_init(&zip, q1, q2); 146 | 147 | size_t i = 0; 148 | 149 | void *e1, *e2; 150 | while (queue_zip_iter_next(&zip, &e1, &e2) != CC_ITER_END) { 151 | if (i == 0) { 152 | cc_assert(strcmp((char*) e1, "d") == 0, 153 | cc_msg("queue_zip_iter_next: Expected e1 was \"a\" at index 0, but got %s instead", 154 | (char*) e1)); 155 | cc_assert(strcmp((char*) e2, "g") == 0, 156 | cc_msg("queue_zip_iter_next: Expected e1 was \"e\" at index 0, but got %s instead", 157 | (char*) e2)); 158 | } 159 | if (i == 2) { 160 | cc_assert(strcmp((char*) e1, "b") == 0, 161 | cc_msg("queue_zip_iter_next: Expected e1 was \"a\" at index 2, but got %s instead", 162 | (char*) e1)); 163 | cc_assert(strcmp((char*) e2, "e") == 0, 164 | cc_msg("queue_zip_iter_next: Expected e1 was \"e\" at index 2, but got %s instead", 165 | (char*) e2)); 166 | } 167 | i++; 168 | } 169 | cc_assert(i == 3, 170 | cc_msg("queue_zip_iter_next: Expected 3 iterations, but got %d instead", i)); 171 | 172 | queue_destroy(q1); 173 | queue_destroy(q2); 174 | } 175 | 176 | 177 | void test_queue_zip_iter() 178 | { 179 | test_queue_zip_iter_next(); 180 | } 181 | -------------------------------------------------------------------------------- /static test data/Collections-C/test/stack_test.c: -------------------------------------------------------------------------------- 1 | #include "../src/stack.h" 2 | #include "test.h" 3 | #include 4 | 5 | void test_stack_push(); 6 | void test_stack_pop(); 7 | 8 | int main(int argc, char **argv) 9 | { 10 | cc_set_exit_on_failure(false); 11 | 12 | test_stack_push(); 13 | test_stack_pop(); 14 | 15 | return cc_get_status(); 16 | } 17 | 18 | void test_stack_push() 19 | { 20 | Stack *s; 21 | stack_new(&s); 22 | 23 | int a = 1; 24 | int b = 2; 25 | int c = 3; 26 | 27 | int *p; 28 | 29 | stack_push(s, (void*)&a); 30 | stack_peek(s, (void*)&p); 31 | cc_assert(p == &a, 32 | cc_msg("stack_push: Top stack element not as expected")); 33 | 34 | stack_push(s, (void*) &b); 35 | stack_peek(s, (void*)&p); 36 | cc_assert(p == &b, 37 | cc_msg("stack_push: Top stack element not as expected")); 38 | 39 | stack_push(s, (void*)&c); 40 | stack_peek(s, (void*)&p); 41 | cc_assert(p == &c, 42 | cc_msg("stack_push: Top stack element not as expected")); 43 | 44 | stack_destroy(s); 45 | 46 | } 47 | 48 | void test_stack_pop() 49 | { 50 | Stack *s; 51 | stack_new(&s); 52 | 53 | int a = 1; 54 | int b = 2; 55 | int c = 3; 56 | 57 | stack_push(s, (void*)&a); 58 | stack_push(s, (void*)&b); 59 | stack_push(s, (void*)&c); 60 | 61 | int *pop; 62 | int *peek; 63 | 64 | stack_pop(s, (void*)&pop); 65 | cc_assert(pop == &c, 66 | cc_msg("stack_pop: Top stack element not as expected")); 67 | 68 | stack_peek(s, (void*)&peek); 69 | cc_assert(peek == &b, 70 | cc_msg("stack_pop: Top stack element not as expected")); 71 | 72 | stack_destroy(s); 73 | } 74 | -------------------------------------------------------------------------------- /static test data/Collections-C/test/test.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | 3 | int test_status = PASS; 4 | bool exit_on_failure = false; 5 | 6 | const size_t msg_size = 256; 7 | 8 | char msg_buff[256]; 9 | char *assert_msg = "Assertion failure at "; 10 | 11 | void cc_assert(bool exp, char *msg) 12 | { 13 | if (!exp) { 14 | test_status = FAIL; 15 | printf("%s%s\n", assert_msg, msg); 16 | if (exit_on_failure) 17 | exit(FAIL); 18 | } 19 | } 20 | 21 | char *cc_msg(char *format, ...) 22 | { 23 | va_list args; 24 | va_start(args, format); 25 | 26 | vsnprintf(msg_buff, msg_size, format, args); 27 | 28 | va_end(args); 29 | return msg_buff; 30 | } 31 | 32 | void cc_set_status(int status) 33 | { 34 | test_status = status; 35 | } 36 | 37 | void cc_set_exit_on_failure(bool exit) 38 | { 39 | exit_on_failure = exit; 40 | } 41 | 42 | int cc_get_status() 43 | { 44 | return test_status; 45 | } 46 | -------------------------------------------------------------------------------- /static test data/Collections-C/test/test.h: -------------------------------------------------------------------------------- 1 | #ifndef TEST_H_ 2 | #define TEST_H_ 3 | 4 | #define PASS 0 5 | #define SKIP 77 6 | #define ERROR 99 7 | #define FAIL 1 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | void cc_assert(bool expression, char* buff); 15 | char *cc_msg(char *format, ...); 16 | 17 | void cc_set_status(int s); 18 | void cc_set_exit_on_failure(bool exit); 19 | int cc_get_status(); 20 | 21 | #endif /* TEST_H_ */ 22 | 23 | -------------------------------------------------------------------------------- /static test data/Collections-C/test/treeset_test.c: -------------------------------------------------------------------------------- 1 | #include "test.h" 2 | #include "../src/treeset.h" 3 | 4 | void test_treeset_add(); 5 | void test_treeset_remove(); 6 | void test_treeset_remove_all(); 7 | void test_treeset_size(); 8 | 9 | int main(int argc, char **argv) 10 | { 11 | cc_set_exit_on_failure(false); 12 | 13 | test_treeset_add(); 14 | test_treeset_remove(); 15 | test_treeset_remove_all(); 16 | test_treeset_size(); 17 | 18 | return cc_get_status(); 19 | } 20 | 21 | int cmp(const void *k1, const void *k2) 22 | { 23 | int a = *((int*) k1); 24 | int b = *((int*) k2); 25 | 26 | if (a < b) 27 | return -1; 28 | else if (a > b) 29 | return 1; 30 | else 31 | return 0; 32 | } 33 | 34 | void test_treeset_add() 35 | { 36 | TreeSet *set; 37 | treeset_new(cmp, &set); 38 | 39 | int a = 1; 40 | int b = 2; 41 | int c = 3; 42 | 43 | treeset_add(set, &a); 44 | treeset_add(set, &b); 45 | treeset_add(set, &c); 46 | treeset_add(set, &c); 47 | 48 | size_t size = treeset_size(set); 49 | 50 | cc_assert(size == 3, 51 | cc_msg("treeset_add: Expected size was 3, but got %d", 52 | size)); 53 | 54 | cc_assert(treeset_contains(set, &a) && 55 | treeset_contains(set, &b), 56 | cc_msg("treeset_add: TreeSet expected to contain elemnts" 57 | " %d and %d", a, b)); 58 | 59 | treeset_destroy(set); 60 | } 61 | 62 | void test_treeset_remove() 63 | { 64 | TreeSet *set; 65 | treeset_new(cmp, &set); 66 | 67 | int a = 1; 68 | int b = 2; 69 | int c = 3; 70 | 71 | treeset_add(set, &a); 72 | treeset_add(set, &b); 73 | treeset_add(set, &c); 74 | 75 | treeset_remove(set, &a, NULL); 76 | 77 | size_t size = treeset_size(set); 78 | 79 | cc_assert(size == 2, 80 | cc_msg("treeset_add: Expected size was 2, but got %d", 81 | size)); 82 | 83 | cc_assert(!treeset_contains(set, &a), 84 | cc_msg("treeset_add: TreeSet not expected to contain " 85 | "element %d", a)); 86 | 87 | treeset_destroy(set); 88 | } 89 | 90 | void test_treeset_remove_all() 91 | { 92 | TreeSet *set; 93 | treeset_new(cmp, &set); 94 | 95 | int a = 1; 96 | int b = 2; 97 | int c = 3; 98 | 99 | treeset_add(set, &a); 100 | treeset_add(set, &b); 101 | treeset_add(set, &c); 102 | 103 | treeset_remove_all(set); 104 | 105 | size_t size = treeset_size(set); 106 | 107 | cc_assert(size == 0, 108 | cc_msg("treeset_add: Expected size was 0, but got %d", 109 | size)); 110 | 111 | cc_assert(!treeset_contains(set, &a) && 112 | !treeset_contains(set, &c), 113 | cc_msg("treeset_add: TreeSet not empty after removing" 114 | " all elements")); 115 | 116 | treeset_destroy(set); 117 | } 118 | 119 | void test_treeset_size() 120 | { 121 | TreeSet *set; 122 | treeset_new(cmp, &set); 123 | 124 | int a = 1; 125 | int b = 2; 126 | int c = 3; 127 | 128 | treeset_add(set, &a); 129 | treeset_add(set, &b); 130 | treeset_add(set, &c); 131 | 132 | cc_assert(treeset_size(set) == 3, 133 | cc_msg("treeset_size: Unexpected set size")); 134 | 135 | treeset_destroy(set); 136 | } 137 | 138 | void test_treeset_iter_next() 139 | { 140 | TreeSet *t; 141 | treeset_new(cmp, &t); 142 | 143 | int a = 1; 144 | int b = 2; 145 | int c = 3; 146 | int d = 4; 147 | 148 | treeset_add(t, &a); 149 | treeset_add(t, &b); 150 | treeset_add(t, &c); 151 | treeset_add(t, &d); 152 | 153 | int one = 0; 154 | int two = 0; 155 | int three = 0; 156 | int four = 0; 157 | 158 | TreeSetIter iter; 159 | treeset_iter_init(&iter, t); 160 | 161 | void *e; 162 | while (treeset_iter_next(&iter, &e) != CC_ITER_END) { 163 | if (*((int*)e) == a) 164 | one++; 165 | 166 | if (*((int*)e) == b) 167 | two++; 168 | 169 | if (*((int*)e) == c) 170 | three++; 171 | 172 | if (*((int*)e) == d) 173 | four++; 174 | } 175 | 176 | bool asrt = (one == 1) && (two == 1) && 177 | (three == 1) && (four == 1); 178 | 179 | cc_assert(asrt, 180 | cc_msg("treeset_iter_next: Unexpected number" 181 | " of entries returned")); 182 | 183 | treeset_destroy(t); 184 | } 185 | 186 | void test_treeset_iter_remove() 187 | { 188 | TreeSet *t; 189 | treeset_new(cmp, &t); 190 | 191 | int a = 1; 192 | int b = 2; 193 | int c = 3; 194 | 195 | treeset_add(t, &a); 196 | treeset_add(t, &b); 197 | treeset_add(t, &c); 198 | 199 | TreeSetIter iter; 200 | treeset_iter_init(&iter, t); 201 | 202 | void *e; 203 | while (treeset_iter_next(&iter, &e) != CC_ITER_END) { 204 | if (*((int*)e) == b) 205 | treeset_iter_remove(&iter, NULL); 206 | } 207 | 208 | cc_assert(treeset_size(t) == 2, 209 | cc_msg("treeset_iter_remove: Expected size 2 but got %d ", 210 | treeset_size(t))); 211 | 212 | cc_assert(!treeset_contains(t, &b), 213 | cc_msg("treeset_iter_remove: Element b still pressent " 214 | "after removal")); 215 | 216 | treeset_destroy(t); 217 | } 218 | -------------------------------------------------------------------------------- /static test data/Collections-C/test/treetable_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../src/treetable.h" 5 | #include "../src/deque.h" 6 | #include "test.h" 7 | 8 | void test_treetable_add(); 9 | void test_treetable_remove(); 10 | void test_treetable_remove_all(); 11 | void test_treetable_get(); 12 | void test_treetable_size(); 13 | void test_treetable_get_first(); 14 | void test_treetable_get_last(); 15 | void test_treetable_remove_first(); 16 | void test_treetable_remove_last(); 17 | void test_treetable_get_greater_than(); 18 | void test_treetable_get_lesser_than(); 19 | void test_treetable_foreach(); 20 | void test_treetable_iter(); 21 | 22 | #ifdef DEBUG 23 | void test_rb_structure(); 24 | char *error_code_to_string(int code); 25 | #endif 26 | 27 | int main(int argc, char **argv) 28 | { 29 | #ifdef DEBUG 30 | cc_set_exit_on_failure(true); 31 | test_rb_structure(); 32 | #endif 33 | cc_set_exit_on_failure(false); 34 | test_treetable_add(); 35 | test_treetable_remove(); 36 | test_treetable_remove_all(); 37 | test_treetable_get(); 38 | test_treetable_size(); 39 | test_treetable_get_first(); 40 | test_treetable_get_last(); 41 | test_treetable_remove_first(); 42 | test_treetable_remove_last(); 43 | test_treetable_get_greater_than(); 44 | test_treetable_get_lesser_than(); 45 | test_treetable_iter(); 46 | 47 | return cc_get_status(); 48 | } 49 | 50 | int cmp(const void *k1, const void *k2) 51 | { 52 | int a = *((int*) k1); 53 | int b = *((int*) k2); 54 | 55 | if (a < b) 56 | return -1; 57 | else if (a > b) 58 | return 1; 59 | else 60 | return 0; 61 | } 62 | 63 | void test_treetable_add() 64 | { 65 | TreeTable *table; 66 | treetable_new(cmp, &table); 67 | 68 | int a = 1; 69 | int b = 2; 70 | int c = 3; 71 | int d = 4; 72 | int e = 5; 73 | int f = 6; 74 | int g = 7; 75 | int h = 8; 76 | 77 | treetable_add(table, &a, "a"); 78 | treetable_add(table, &b, "b"); 79 | treetable_add(table, &c, "c"); 80 | treetable_add(table, &d, "d"); 81 | treetable_add(table, &e, "e"); 82 | treetable_add(table, &f, "f"); 83 | treetable_add(table, &g, "g"); 84 | treetable_add(table, &h, "h"); 85 | 86 | cc_assert(treetable_contains_key(table, &a), 87 | cc_msg("treetable_add: Added key not found")); 88 | 89 | cc_assert(treetable_contains_key(table, &e), 90 | cc_msg("treetable_add: Added key not found")); 91 | 92 | treetable_destroy(table); 93 | } 94 | 95 | void test_treetable_remove() 96 | { 97 | TreeTable *table; 98 | treetable_new(cmp, &table); 99 | 100 | int a = 1; 101 | int b = 2; 102 | int c = 3; 103 | int d = 4; 104 | int e = 5; 105 | int f = 6; 106 | int g = 7; 107 | int h = 8; 108 | 109 | treetable_add(table, &a, "a"); 110 | treetable_add(table, &b, "b"); 111 | treetable_add(table, &c, "c"); 112 | treetable_add(table, &d, "d"); 113 | treetable_add(table, &e, "e"); 114 | treetable_add(table, &f, "f"); 115 | treetable_add(table, &g, "g"); 116 | treetable_add(table, &h, "h"); 117 | 118 | treetable_remove(table, &f, NULL); 119 | 120 | cc_assert(!treetable_contains_key(table, &f), 121 | cc_msg("treetable_remove: Removed key still present")); 122 | 123 | treetable_destroy(table); 124 | 125 | } 126 | 127 | void test_treetable_remove_all() 128 | { 129 | TreeTable *table; 130 | treetable_new(cmp, &table); 131 | 132 | int a = 1; 133 | int b = 2; 134 | int c = 3; 135 | int d = 4; 136 | 137 | treetable_add(table, &a, "a"); 138 | treetable_add(table, &b, "b"); 139 | treetable_add(table, &c, "c"); 140 | treetable_add(table, &d, "d"); 141 | 142 | treetable_remove_all(table); 143 | 144 | cc_assert(treetable_size(table) == 0, 145 | cc_msg("treetable_remove_all: Table size not 0")); 146 | 147 | cc_assert(!treetable_contains_key(table, &a), 148 | cc_msg("treetable_remove_all: Removed key still present")); 149 | 150 | cc_assert(!treetable_contains_key(table, &b), 151 | cc_msg("treetable_remove_all: Removed key still present")); 152 | 153 | cc_assert(!treetable_contains_key(table, &c), 154 | cc_msg("treetable_remove_all: Removed key still present")); 155 | 156 | cc_assert(!treetable_contains_key(table, &d), 157 | cc_msg("treetable_remove_all: Removed key still present")); 158 | 159 | treetable_destroy(table); 160 | } 161 | 162 | void test_treetable_get() 163 | { 164 | TreeTable *table; 165 | treetable_new(cmp, &table); 166 | 167 | int a = 1; 168 | int b = 2; 169 | int c = 3; 170 | 171 | treetable_add(table, &a, "a"); 172 | treetable_add(table, &b, "b"); 173 | treetable_add(table, &c, "c"); 174 | 175 | char *ra; 176 | char *rb; 177 | char *rc; 178 | treetable_get(table, &a, (void*) &ra); 179 | treetable_get(table, &b, (void*) &rb); 180 | treetable_get(table, &c, (void*) &rc); 181 | 182 | cc_assert(strcmp(ra, "a") == 0, 183 | cc_msg("treetable_get: Retrieved value not as expected")); 184 | 185 | cc_assert(strcmp(rb, "b") == 0, 186 | cc_msg("treetable_get: Retrieved value not as expected")); 187 | 188 | cc_assert(strcmp(rc, "c") == 0, 189 | cc_msg("treetable_get: Retrieved value not as expected")); 190 | 191 | treetable_destroy(table); 192 | } 193 | 194 | void test_treetable_size() 195 | { 196 | TreeTable *table; 197 | treetable_new(cmp, &table); 198 | 199 | int a = 1; 200 | int b = 2; 201 | int c = 3; 202 | 203 | treetable_add(table, &a, "a"); 204 | treetable_add(table, &b, "b"); 205 | treetable_add(table, &c, "c"); 206 | 207 | cc_assert(treetable_size(table) == 3, 208 | cc_msg("treetable_size: Unexpected table size")); 209 | 210 | treetable_destroy(table); 211 | } 212 | 213 | void test_treetable_get_first() 214 | { 215 | TreeTable *table; 216 | treetable_new(cmp, &table); 217 | 218 | int a = 1; 219 | int b = 2; 220 | int c = 3; 221 | int d = 4; 222 | 223 | treetable_add(table, &c, "a"); 224 | treetable_add(table, &d, "b"); 225 | treetable_add(table, &b, "c"); 226 | treetable_add(table, &a, "d"); 227 | 228 | int *first; 229 | treetable_get_first_key(table, (void*) &first); 230 | 231 | cc_assert(*first == a, 232 | cc_msg("treetable_get_first_key: first %d, expected %d instead", 233 | *first, a)); 234 | 235 | treetable_destroy(table); 236 | } 237 | 238 | void test_treetable_get_last() 239 | { 240 | TreeTable *table; 241 | treetable_new(cmp, &table); 242 | 243 | int a = 1; 244 | int b = 2; 245 | int c = 3; 246 | int d = 4; 247 | 248 | treetable_add(table, &c, "a"); 249 | treetable_add(table, &d, "b"); 250 | treetable_add(table, &b, "c"); 251 | treetable_add(table, &a, "d"); 252 | 253 | int *last; 254 | treetable_get_last_key(table, (void*) &last); 255 | 256 | cc_assert(*last == d, 257 | cc_msg("treetable_get_last_key: last %d, expected %d instead", 258 | *last, d)); 259 | 260 | treetable_destroy(table); 261 | } 262 | 263 | void test_treetable_remove_first() 264 | { 265 | TreeTable *table; 266 | treetable_new(cmp, &table); 267 | 268 | int a = 1; 269 | int b = 2; 270 | int c = 3; 271 | int d = 4; 272 | 273 | treetable_add(table, &c, "a"); 274 | treetable_add(table, &d, "b"); 275 | treetable_add(table, &b, "c"); 276 | treetable_add(table, &a, "d"); 277 | 278 | treetable_remove_first(table, NULL); 279 | 280 | cc_assert(!treetable_contains_key(table, &a), 281 | cc_msg("treetable_remove_first: Key still present after removal")); 282 | 283 | treetable_destroy(table); 284 | } 285 | 286 | void test_treetable_remove_last() 287 | { 288 | TreeTable *table; 289 | treetable_new(cmp, &table); 290 | 291 | int a = 1; 292 | int b = 2; 293 | int c = 3; 294 | int d = 4; 295 | 296 | treetable_add(table, &c, "a"); 297 | treetable_add(table, &d, "b"); 298 | treetable_add(table, &b, "c"); 299 | treetable_add(table, &a, "d"); 300 | 301 | treetable_remove_last(table, NULL); 302 | 303 | cc_assert(!treetable_contains_key(table, &d), 304 | cc_msg("treetable_remove_last: Key still present after removal")); 305 | 306 | treetable_destroy(table); 307 | } 308 | 309 | void test_treetable_get_greater_than() 310 | { 311 | TreeTable *table; 312 | treetable_new(cmp, &table); 313 | 314 | int a = 1; 315 | int b = 2; 316 | int c = 3; 317 | int d = 4; 318 | 319 | treetable_add(table, &c, "a"); 320 | treetable_add(table, &d, "b"); 321 | treetable_add(table, &b, "c"); 322 | treetable_add(table, &a, "d"); 323 | 324 | int *g; 325 | treetable_get_greater_than(table, &b, (void*) &g); 326 | 327 | cc_assert(*g == c, 328 | cc_msg("treetable_get_greater_than: Expected key was %d, but got " 329 | "%d instead", c, *g)); 330 | 331 | treetable_destroy(table); 332 | } 333 | 334 | void test_treetable_get_lesser_than() 335 | { 336 | TreeTable *table; 337 | treetable_new(cmp, &table); 338 | 339 | int a = 1; 340 | int b = 2; 341 | int c = 3; 342 | int d = 4; 343 | 344 | treetable_add(table, &c, "a"); 345 | treetable_add(table, &d, "b"); 346 | treetable_add(table, &b, "c"); 347 | treetable_add(table, &a, "d"); 348 | 349 | int *g; 350 | treetable_get_lesser_than(table, &b, (void*) &g); 351 | 352 | cc_assert(*g == a, 353 | cc_msg("treetable_get_lesser_than: Expected key was %d, but got " 354 | "%d instead", a, *g)); 355 | 356 | treetable_destroy(table); 357 | } 358 | 359 | 360 | void test_treetable_iter_next() 361 | { 362 | TreeTable *t; 363 | treetable_new(cmp, &t); 364 | 365 | int a = 1; 366 | int b = 2; 367 | int c = 3; 368 | int d = 4; 369 | 370 | treetable_add(t, &a, "1"); 371 | treetable_add(t, &b, "2"); 372 | treetable_add(t, &c, "3"); 373 | treetable_add(t, &d, "5"); 374 | 375 | int one = 0; 376 | int two = 0; 377 | int three = 0; 378 | int four = 0; 379 | 380 | TreeTableIter iter; 381 | treetable_iter_init(&iter, t); 382 | 383 | TreeTableEntry entry; 384 | while (treetable_iter_next(&iter, &entry) != CC_ITER_END) { 385 | int const *key = entry.key; 386 | 387 | if (*key == a) 388 | one++; 389 | 390 | if (*key == b) 391 | two++; 392 | 393 | if (*key == c) 394 | three++; 395 | 396 | if (*key == d) 397 | four++; 398 | } 399 | 400 | bool asrt = (one == 1) && (two == 1) && 401 | (three == 1) && (four == 1); 402 | 403 | cc_assert(asrt, 404 | cc_msg("treetable_iter_next: Unexpected number" 405 | " of entries returned")); 406 | 407 | treetable_destroy(t); 408 | } 409 | 410 | void test_treetable_iter_remove() 411 | { 412 | TreeTable *t; 413 | treetable_new(cmp, &t); 414 | 415 | int a = 1; 416 | int b = 2; 417 | int c = 3; 418 | 419 | treetable_add(t, &a, "a"); 420 | treetable_add(t, &b, "a"); 421 | treetable_add(t, &c, "a"); 422 | 423 | TreeTableIter iter; 424 | treetable_iter_init(&iter, t); 425 | 426 | TreeTableEntry entry; 427 | while (treetable_iter_next(&iter, &entry) != CC_ITER_END) { 428 | int const *key = entry.key; 429 | 430 | if (*key == b) { 431 | enum cc_stat s; 432 | s = treetable_iter_remove(&iter, NULL); 433 | 434 | cc_assert(s == CC_OK, 435 | cc_msg("treetable_iter_remove: Expected remove success, but" 436 | " got failure instead")); 437 | 438 | s = treetable_iter_remove(&iter, NULL); 439 | 440 | cc_assert(s == CC_ERR_KEY_NOT_FOUND, 441 | cc_msg("treetable_iter_remove: Expected remove failure, but" 442 | " got something else instead")); 443 | } 444 | } 445 | 446 | cc_assert(treetable_size(t) == 2, 447 | cc_msg("treetable_iter_remove: Expected size 2 but got %d ", 448 | treetable_size(t))); 449 | 450 | cc_assert(!treetable_contains_key(t, &b), 451 | cc_msg("treetable_iter_remove: Element b still pressent " 452 | "after removal")); 453 | 454 | treetable_destroy(t); 455 | } 456 | 457 | void test_treetable_iter() 458 | { 459 | test_treetable_iter_next(); 460 | test_treetable_iter_remove(); 461 | } 462 | 463 | 464 | #ifdef DEBUG 465 | char *error_code_to_string(int code) 466 | { 467 | char *msg = malloc(sizeof(char) * 50); 468 | char *m; 469 | 470 | switch (code) { 471 | case RB_ERROR_OK: 472 | m = "RB_ERROR_OK"; 473 | return strcpy(msg, m); 474 | case RB_ERROR_CONSECUTIVE_RED: 475 | m = "RB_ERROR_CONSECUTIVE_RED"; 476 | return strcpy(msg, m); 477 | case RB_ERROR_BLACK_HEIGHT: 478 | m = "RB_ERROR_BLACK_HEIGHT"; 479 | return strcpy(msg, m); 480 | case RB_ERROR_TREE_STRUCTURE: 481 | m = "RB_ERROR_TREE_STRUCTURE"; 482 | return strcpy(msg, m); 483 | default: 484 | sprintf(msg, "UNKNOWN_ERR_CODE: %d", code); 485 | return msg; 486 | } 487 | } 488 | 489 | 490 | void test_rb_structure() 491 | { 492 | /* Thows a whole bunch of random data at the tree to make sure that */ 493 | /* the Red Black properties always hold. */ 494 | 495 | /* fill an array so that we don't have to malloc all these ints */ 496 | int nkeys = 1000; 497 | int rkeys[nkeys]; 498 | 499 | srand(time(NULL)); 500 | 501 | char *dummy = "dummy"; 502 | 503 | /* Easy tracking of how many keys are available after removal */ 504 | Deque *keys; 505 | deque_new(&keys); 506 | TreeTable *tree; 507 | treetable_new(cmp, &tree); 508 | 509 | /* Populate the tree and assert RB validity on each insert */ 510 | int i; 511 | for (i = 0; i < nkeys; i++) { 512 | rkeys[i] = (rand() % 10000); 513 | deque_add(keys, &(rkeys[i])); 514 | treetable_add(tree, &(rkeys[i]), dummy); 515 | 516 | int status = treetable_assert_rb_rules(tree); 517 | char *msg = error_code_to_string(status); 518 | cc_assert(status == RB_ERROR_OK, 519 | cc_msg("Red Black tree validation (insertion) (i=%d): %s", i, msg)); 520 | free(msg); 521 | } 522 | 523 | /* Remove keys at random until all keys are removed and assert Red Black */ 524 | /* validity on each remove. */ 525 | for (i = 0; i < nkeys; i++) { 526 | int *key; 527 | deque_get_at(keys, (rand() % (deque_size(keys)) -1), (void*)&key); 528 | 529 | if (key != NULL) { 530 | treetable_remove(tree, key, NULL); 531 | deque_remove(keys, key, NULL); 532 | } 533 | int status = treetable_assert_rb_rules(tree); 534 | char *msg = error_code_to_string(status); 535 | cc_assert(status == RB_ERROR_OK, 536 | cc_msg("Red Black tree validation (removal) (i=%d): %s", i, msg)); 537 | free(msg); 538 | } 539 | 540 | deque_destroy(keys); 541 | treetable_destroy(tree); 542 | } 543 | #endif 544 | -------------------------------------------------------------------------------- /static test data/another_class.php: -------------------------------------------------------------------------------- 1 | 0 71 | endfunction 72 | 73 | function! s:Test_tags_file_containes_exactly_two_tags() 74 | call s:phptags_file.edit() 75 | normal! gg 76 | let num_lines= line('$') 77 | AssertEquals(2, num_lines) 78 | endfunction 79 | 80 | function! s:Test_tags_file_does_contain_tag_from_supported_file_class() 81 | call s:phptags_file.edit() 82 | normal! gg 83 | let line_num= search('supported_file') 84 | Assert line_num > 0 85 | Assert line_num < 3 86 | endfunction 87 | 88 | function! s:Test_tags_file_does_contain_tag_from_another_class_class() 89 | call s:phptags_file.edit() 90 | normal! gg 91 | let line_num= search('another_class') 92 | Assert line_num > 0 93 | Assert line_num < 3 94 | endfunction 95 | -------------------------------------------------------------------------------- /tests/when_project_file_exists_and_saving_php_file.vim: -------------------------------------------------------------------------------- 1 | UTSuite when project file exists and saving php file 2 | 3 | function! s:setup_script_vars() 4 | let s:data_dir= L_dir(g:project_tags_dir_path.'/generated test data') 5 | let s:static_php_file= L_dir(g:project_tags_dir_path.'/static test data').get_contained_file('supported_file.php') 6 | let s:php_file= s:data_dir.get_contained_file('supported_file.php') 7 | let s:project_file= s:data_dir.get_contained_file('.project_tags.config.vim') 8 | let s:phptags_file= s:data_dir.get_contained_file('phptags') 9 | endfunction 10 | 11 | function! s:Setup() 12 | let s:stopwatch= L_stopwatch() 13 | call s:stopwatch.start() 14 | call s:safe_teardown() 15 | call s:setup_script_vars() 16 | Assert! !s:data_dir.exists() 17 | call s:data_dir.create() 18 | Assert! s:data_dir.exists() 19 | Assert! s:static_php_file.readable() 20 | Assert! !s:php_file.readable() 21 | call s:static_php_file.copy_to(s:php_file.path) 22 | Assert! s:php_file.readable() 23 | Assert! s:php_file.writable() 24 | Assert! !s:project_file.readable() 25 | call s:project_file.create() 26 | Assert! s:project_file.readable() 27 | Assert! s:project_file.writable() 28 | call s:php_file.edit() 29 | Assert! !s:phptags_file.readable() 30 | Assert! !s:phptags_file.writable() 31 | w 32 | endfunction 33 | 34 | function! s:safe_teardown() 35 | call s:setup_script_vars() 36 | if s:data_dir.exists() 37 | call s:data_dir.delete() 38 | endif 39 | endfunction 40 | 41 | function! s:Teardown() 42 | call s:setup_script_vars() 43 | Assert s:data_dir.exists() 44 | call s:data_dir.delete() 45 | Assert !s:data_dir.exists() 46 | let elapsed_milliseconds= s:stopwatch.stop() 47 | Assert elapsed_milliseconds < 1000 48 | endfunction 49 | 50 | function! s:Test_created_tags_file() 51 | Assert s:phptags_file.readable() 52 | endfunction 53 | 54 | function! s:Test_only_files_are_copied_php_file_and_project_file_and_tags_file() 55 | let files= s:data_dir.get_all_files() 56 | AssertEquals(3, len(files)) 57 | Assert s:php_file.path ==# files[0].path || s:php_file.path ==# files[1].path || s:php_file.path ==# files[2].path 58 | Assert s:project_file.path ==# files[0].path || s:project_file.path ==# files[1].path || s:project_file.path ==# files[2].path 59 | Assert s:phptags_file.path ==# files[0].path || s:phptags_file.path ==# files[1].path || s:phptags_file.path ==# files[2].path 60 | endfunction 61 | 62 | function! s:Test_tags_file_not_empty() 63 | Assert s:phptags_file.size() > 0 64 | endfunction 65 | 66 | function! s:Test_tags_file_only_contains_one_tag() 67 | call s:phptags_file.edit() 68 | normal! gg 69 | let num_lines= line('$') 70 | AssertEquals(1, num_lines) 71 | endfunction 72 | 73 | function! s:Test_tags_file_does_contain_tag_from_php_file() 74 | call s:phptags_file.edit() 75 | normal! gg 76 | let line_num= search('supported_file') 77 | AssertEquals(1, line_num) 78 | endfunction 79 | -------------------------------------------------------------------------------- /tests/when_project_file_exists_and_saving_txt_file.vim: -------------------------------------------------------------------------------- 1 | UTSuite when project file exists and saving txt file 2 | 3 | function! s:setup_script_vars() 4 | let s:data_dir= L_dir(g:project_tags_dir_path.'/generated test data') 5 | let s:txt_file= s:data_dir.get_contained_file('text fl.txt') 6 | let s:project_file= s:data_dir.get_contained_file('.project_tags.config.vim') 7 | endfunction 8 | 9 | function! s:Setup() 10 | let s:stopwatch= L_stopwatch() 11 | call s:stopwatch.start() 12 | call s:safe_teardown() 13 | call s:setup_script_vars() 14 | Assert! !s:data_dir.exists() 15 | call s:data_dir.create() 16 | Assert! s:data_dir.exists() 17 | Assert! !s:txt_file.readable() 18 | call s:txt_file.create() 19 | Assert! s:txt_file.readable() 20 | Assert! s:txt_file.writable() 21 | Assert! !s:project_file.readable() 22 | call s:project_file.create() 23 | Assert! s:project_file.readable() 24 | Assert! s:project_file.writable() 25 | call s:txt_file.edit() 26 | w 27 | endfunction 28 | 29 | function! s:safe_teardown() 30 | call s:setup_script_vars() 31 | if s:data_dir.exists() 32 | call s:data_dir.delete() 33 | endif 34 | endfunction 35 | 36 | function! s:Teardown() 37 | call s:setup_script_vars() 38 | Assert s:data_dir.exists() 39 | call s:data_dir.delete() 40 | Assert !s:data_dir.exists() 41 | let elapsed_milliseconds= s:stopwatch.stop() 42 | Assert elapsed_milliseconds < 1000 43 | endfunction 44 | 45 | function! s:Test_not_create_tags_file() 46 | let txttags_file= s:data_dir.get_contained_file('txttags') 47 | Assert !txttags_file.readable() 48 | endfunction 49 | 50 | function! s:Test_only_files_are_original_txt_and_project_files() 51 | let files= s:data_dir.get_all_files() 52 | AssertEquals(2, len(files)) 53 | Assert s:txt_file.path ==# files[0].path || s:txt_file.path ==# files[1].path 54 | Assert s:project_file.path ==# files[0].path || s:project_file.path ==# files[1].path 55 | endfunction 56 | -------------------------------------------------------------------------------- /tests/when_specifying_exclude_dir.vim: -------------------------------------------------------------------------------- 1 | UTSuite when specifying an exclude dir 2 | 3 | function! s:setup_script_vars() 4 | let s:data_dir= L_dir(g:project_tags_dir_path.'/generated test data') 5 | let s:static_data_dir= L_dir(g:project_tags_dir_path.'/static test data') 6 | let s:exclude_dir= s:data_dir.get_contained_dir('exclude dir') 7 | let s:static_php_file= s:static_data_dir.get_contained_file('supported_file.php') 8 | let s:php_file= s:data_dir.get_contained_file('supported_file.php') 9 | let s:another_static_php_file= s:static_data_dir.get_contained_file('another_class.php') 10 | let s:another_php_file= s:exclude_dir.get_contained_file('another_class.php') 11 | let s:static_exclude_project_file= s:static_data_dir.get_contained_file('exclude_dir_project.vim') 12 | let s:project_file= s:data_dir.get_contained_file('.project_tags.config.vim') 13 | let s:phptags_file= s:data_dir.get_contained_file('phptags') 14 | endfunction 15 | 16 | function! s:Setup() 17 | let s:stopwatch= L_stopwatch() 18 | call s:stopwatch.start() 19 | call s:safe_teardown() 20 | call s:setup_script_vars() 21 | Assert! !s:data_dir.exists() 22 | call s:data_dir.create() 23 | Assert! s:data_dir.exists() 24 | Assert! s:static_data_dir.exists() 25 | Assert! s:static_php_file.readable() 26 | Assert! !s:php_file.readable() 27 | call s:static_php_file.copy_to(s:php_file.path) 28 | Assert! s:php_file.readable() 29 | Assert! s:php_file.writable() 30 | Assert! s:static_exclude_project_file.readable() 31 | Assert! !s:project_file.readable() 32 | call s:static_exclude_project_file.copy_to(s:project_file.path) 33 | Assert! s:project_file.readable() 34 | Assert! s:project_file.writable() 35 | Assert! !s:exclude_dir.exists() 36 | call s:exclude_dir.create() 37 | Assert! s:exclude_dir.exists() 38 | Assert! s:another_static_php_file.readable() 39 | Assert! !s:another_php_file.readable() 40 | call s:another_static_php_file.copy_to(s:another_php_file.path) 41 | Assert! s:another_php_file.readable() 42 | Assert! !s:phptags_file.readable() 43 | call s:php_file.edit() 44 | w 45 | endfunction 46 | 47 | function! s:safe_teardown() 48 | call s:setup_script_vars() 49 | if s:data_dir.exists() 50 | call s:data_dir.delete() 51 | endif 52 | endfunction 53 | 54 | function! s:Teardown() 55 | call s:setup_script_vars() 56 | Assert s:data_dir.exists() 57 | call s:data_dir.delete() 58 | Assert !s:data_dir.exists() 59 | let elapsed_milliseconds= s:stopwatch.stop() 60 | Assert elapsed_milliseconds < 1000 61 | endfunction 62 | 63 | function! s:Test_accepted_project_file_exclude_setting() 64 | AssertEquals(1, len(g:project_tags_exclude)) 65 | AssertEquals('exclude dir', g:project_tags_exclude[0]) 66 | endfunction 67 | 68 | function! s:Test_created_tags_file() 69 | Assert s:phptags_file.readable() 70 | Assert s:phptags_file.writable() 71 | endfunction 72 | 73 | function! s:Test_only_3_files_in_data_dir() 74 | let files= s:data_dir.get_all_files() 75 | AssertEquals(3, len(files)) 76 | endfunction 77 | 78 | function! s:Test_tags_file_does_not_contain_tags_from_excluded_dir() 79 | call s:phptags_file.edit() 80 | normal! gg 81 | let line_num= search('another_class') 82 | AssertEquals(0, line_num) 83 | endfunction 84 | -------------------------------------------------------------------------------- /tests/when_specifying_include_dir_and_saving_code_from_the_project_dir.vim: -------------------------------------------------------------------------------- 1 | UTSuite when specifying an include dir and saving code from the project dir 2 | 3 | function! s:setup_script_vars() 4 | let s:static_data_dir= L_dir(g:project_tags_dir_path.'/static test data') 5 | let s:static_php_file= s:static_data_dir.get_contained_file('supported_file.php') 6 | let s:static_another_php_file= s:static_data_dir.get_contained_file('another_class.php') 7 | let s:static_include_project_file= s:static_data_dir.get_contained_file('include_dir_project.vim') 8 | 9 | let s:data_dir= L_dir(g:project_tags_dir_path.'/generated test data') 10 | let s:include_dir= s:data_dir.get_contained_dir('include dir') 11 | let s:another_php_file= s:include_dir.get_contained_file('another_class.php') 12 | let s:proj_dir= s:data_dir.get_contained_dir('proj dir') 13 | let s:project_file= s:proj_dir.get_contained_file('.project_tags.config.vim') 14 | let s:php_file= s:proj_dir.get_contained_file('supported_file.php') 15 | let s:phptags_file= s:proj_dir.get_contained_file('phptags') 16 | endfunction 17 | 18 | function! s:Setup() 19 | let s:stopwatch= L_stopwatch() 20 | call s:stopwatch.start() 21 | call s:safe_teardown() 22 | call s:setup_script_vars() 23 | 24 | Assert! s:static_data_dir.exists() 25 | Assert! s:static_php_file.readable() 26 | Assert! s:static_include_project_file.readable() 27 | 28 | Assert! !s:data_dir.exists() 29 | call s:data_dir.create() 30 | Assert! s:data_dir.exists() 31 | Assert! !s:include_dir.exists() 32 | call s:include_dir.create() 33 | Assert! s:include_dir.exists() 34 | Assert! !s:another_php_file.readable() 35 | call s:static_another_php_file.copy_to(s:another_php_file.path) 36 | Assert! s:another_php_file.readable() 37 | Assert! !s:proj_dir.exists() 38 | call s:proj_dir.create() 39 | Assert! s:proj_dir.exists() 40 | Assert! !s:project_file.readable() 41 | call s:static_include_project_file.copy_to(s:project_file.path) 42 | Assert! s:project_file.readable() 43 | Assert! !s:php_file.readable() 44 | call s:static_php_file.copy_to(s:php_file.path) 45 | Assert! s:php_file.readable() 46 | Assert! !s:phptags_file.readable() 47 | 48 | call s:php_file.edit() 49 | call l#log('test before save') 50 | w 51 | call l#log('after save') 52 | endfunction 53 | 54 | function! s:safe_teardown() 55 | call s:setup_script_vars() 56 | if s:data_dir.exists() 57 | call s:data_dir.delete() 58 | endif 59 | endfunction 60 | 61 | function! s:Teardown() 62 | call s:setup_script_vars() 63 | Assert s:data_dir.exists() 64 | call s:data_dir.delete() 65 | Assert !s:data_dir.exists() 66 | let elapsed_milliseconds= s:stopwatch.stop() 67 | Assert elapsed_milliseconds < 1000 68 | endfunction 69 | 70 | function! s:Test_accepted_project_file_include_setting() 71 | call l#log('test: before check include setting') 72 | AssertEquals(1, len(g:project_tags_include)) 73 | AssertEquals('../include dir', g:project_tags_include[0]) 74 | endfunction 75 | 76 | function! s:Test_created_tags_file() 77 | Assert s:phptags_file.readable() 78 | Assert s:phptags_file.writable() 79 | endfunction 80 | 81 | function! s:Test_3_files_in_proj_dir() 82 | let files= s:proj_dir.get_all_files() 83 | AssertEquals(3, len(files)) 84 | endfunction 85 | 86 | function! s:Test_tags_file_does_contain_tags_from_included_dir() 87 | call s:phptags_file.edit() 88 | normal! gg 89 | let line_num= search('supported_file') 90 | AssertEquals(1, line_num) 91 | endfunction 92 | -------------------------------------------------------------------------------- /tests/when_working_with_c_project_and_project_file_exists_and_saving_c_file.vim: -------------------------------------------------------------------------------- 1 | UTSuite when working with a C project, and a project file exists and saving a .c file 2 | 3 | function! s:setup_script_vars() 4 | let s:static_c_proj_dir= L_dir(g:project_tags_dir_path.'/static test data').get_contained_dir('Collections-C') 5 | let s:data_dir= L_dir(g:project_tags_dir_path.'/generated test data') 6 | let s:c_proj_dir= s:data_dir.get_contained_dir('Collections-C') 7 | let s:c_file= s:c_proj_dir.get_contained_file('src/array.c') 8 | let s:project_file= s:c_proj_dir.get_contained_file('.project_tags.config.vim') 9 | let s:ctags_file= s:c_proj_dir.get_contained_file('ctags') 10 | endfunction 11 | 12 | function! s:Setup() 13 | let s:stopwatch= L_stopwatch() 14 | call s:stopwatch.start() 15 | call s:safe_teardown() 16 | call project_tags#add_language('ctags', ['c', 'h']) 17 | call s:setup_script_vars() 18 | Assert! s:static_c_proj_dir.exists() 19 | Assert! !s:data_dir.exists() 20 | call s:data_dir.create() 21 | Assert! s:data_dir.exists() 22 | Assert! !s:c_proj_dir.exists() 23 | Assert! !s:c_file.readable() 24 | call s:static_c_proj_dir.copy_to(s:c_proj_dir) 25 | Assert! s:c_file.readable() 26 | Assert! s:c_file.writable() 27 | Assert! !s:project_file.readable() 28 | call s:project_file.create() 29 | Assert! s:project_file.readable() 30 | Assert! s:project_file.writable() 31 | call s:c_file.edit() 32 | Assert! !s:ctags_file.readable() 33 | Assert! !s:ctags_file.writable() 34 | w 35 | endfunction 36 | 37 | function! s:safe_teardown() 38 | call project_tags#remove_all_languages() 39 | call project_tags#add_built_in_language_support() 40 | call s:setup_script_vars() 41 | if s:data_dir.exists() 42 | call s:data_dir.delete() 43 | endif 44 | endfunction 45 | 46 | function! s:Teardown() 47 | call project_tags#remove_all_languages() 48 | call project_tags#add_built_in_language_support() 49 | call s:setup_script_vars() 50 | Assert s:data_dir.exists() 51 | call s:data_dir.delete() 52 | Assert !s:data_dir.exists() 53 | let elapsed_milliseconds= s:stopwatch.stop() 54 | Assert elapsed_milliseconds < 2000 55 | endfunction 56 | 57 | function! s:Test_created_tags_file() 58 | Assert! s:ctags_file.readable() 59 | endfunction 60 | 61 | " function! s:Test_tags_file_not_empty() 62 | " Assert s:ctags_file.size() > 0 63 | " endfunction 64 | 65 | " function! s:Test_tags_file_does_contain_tag_from_edited_c_file() 66 | " call s:ctags_file.edit() 67 | " normal! gg 68 | " let line_num= search('expand_capacity') 69 | " Assert line_num > 0 70 | " endfunction 71 | 72 | " function! s:Test_tags_file_does_contain_tag_from_different_c_file() 73 | " call s:ctags_file.edit() 74 | " normal! gg 75 | " let line_num= search('hashset_conf_init') 76 | " Assert line_num > 0 77 | " endfunction 78 | 79 | " function! s:Test_tags_file_does_contain_tag_from_h_file() 80 | " call s:ctags_file.edit() 81 | " normal! gg 82 | " let line_num= search('list_iter_s') 83 | " Assert line_num > 0 84 | " endfunction 85 | -------------------------------------------------------------------------------- /tests/when_working_with_c_project_and_project_file_exists_and_saving_h_file.vim: -------------------------------------------------------------------------------- 1 | UTSuite when working with a C project, and a project file exists and saving a .h file 2 | 3 | function! s:setup_script_vars() 4 | let s:static_c_proj_dir= L_dir(g:project_tags_dir_path.'/static test data').get_contained_dir('Collections-C') 5 | let s:data_dir= L_dir(g:project_tags_dir_path.'/generated test data') 6 | let s:c_proj_dir= s:data_dir.get_contained_dir('Collections-C') 7 | let s:h_file= s:c_proj_dir.get_contained_file('src/hashset.h') 8 | let s:project_file= s:c_proj_dir.get_contained_file('.project_tags.config.vim') 9 | let s:ctags_file= s:c_proj_dir.get_contained_file('ctags') 10 | endfunction 11 | 12 | function! s:Setup() 13 | let s:stopwatch= L_stopwatch() 14 | call s:stopwatch.start() 15 | call s:safe_teardown() 16 | call project_tags#add_language('ctags', ['c', 'h']) 17 | call s:setup_script_vars() 18 | Assert! s:static_c_proj_dir.exists() 19 | Assert! !s:data_dir.exists() 20 | call s:data_dir.create() 21 | Assert! s:data_dir.exists() 22 | Assert! !s:c_proj_dir.exists() 23 | Assert! !s:h_file.readable() 24 | call s:static_c_proj_dir.copy_to(s:c_proj_dir) 25 | Assert! s:h_file.readable() 26 | Assert! s:h_file.writable() 27 | Assert! !s:project_file.readable() 28 | call s:project_file.create() 29 | Assert! s:project_file.readable() 30 | Assert! s:project_file.writable() 31 | call s:h_file.edit() 32 | Assert! !s:ctags_file.readable() 33 | Assert! !s:ctags_file.writable() 34 | w 35 | endfunction 36 | 37 | function! s:safe_teardown() 38 | call project_tags#remove_all_languages() 39 | call project_tags#add_built_in_language_support() 40 | call s:setup_script_vars() 41 | if s:data_dir.exists() 42 | call s:data_dir.delete() 43 | endif 44 | endfunction 45 | 46 | function! s:Teardown() 47 | call project_tags#remove_all_languages() 48 | call project_tags#add_built_in_language_support() 49 | call s:setup_script_vars() 50 | Assert s:data_dir.exists() 51 | call s:data_dir.delete() 52 | Assert !s:data_dir.exists() 53 | let elapsed_milliseconds= s:stopwatch.stop() 54 | Assert elapsed_milliseconds < 2000 55 | endfunction 56 | 57 | function! s:Test_created_tags_file() 58 | Assert! s:ctags_file.readable() 59 | endfunction 60 | 61 | function! s:Test_tags_file_not_empty() 62 | Assert s:ctags_file.size() > 0 63 | endfunction 64 | 65 | function! s:Test_tags_file_does_contain_tag_from_edited_h_file() 66 | let tags_file= L_tags_file(s:ctags_file.path) 67 | let tag_list= tags_file.get_tags('hashset_conf_init') 68 | Assert len(tag_list) > 0 69 | endfunction 70 | 71 | function! s:Test_tags_file_does_contain_tag_from_different_h_file() 72 | let tags_file= L_tags_file(s:ctags_file.path) 73 | let tag_list= tags_file.get_tags('list_iter_s') 74 | Assert len(tag_list) > 0 75 | endfunction 76 | 77 | function! s:Test_tags_file_does_contain_tag_from_c_file() 78 | let tags_file= L_tags_file(s:ctags_file.path) 79 | let tag_list= tags_file.get_tags('expand_capacity') 80 | Assert len(tag_list) > 0 81 | endfunction 82 | --------------------------------------------------------------------------------