├── .gitignore ├── .ignore ├── LICENSE ├── README.org ├── config.nims ├── src ├── config.nims └── std_vector.nim ├── std_vector.nimble └── tests └── test.nim /.gitignore: -------------------------------------------------------------------------------- 1 | # Trick to ignore extension-less binaries 2 | # Ignore all 3 | * 4 | 5 | # Unignore all with extensions 6 | !*.* 7 | 8 | # Unignore all dirs 9 | !*/ 10 | 11 | /public 12 | htmldocs 13 | -------------------------------------------------------------------------------- /.ignore: -------------------------------------------------------------------------------- 1 | public/* 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Kaushal Modi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | #+title: Nim wrapper for C++ std::vector 2 | 3 | *The contents of this repo have now transferred to 4 | https://github.com/Clonkk/nim-cppstl. This repo has been archived as 5 | of 2021/06/28.* 6 | 7 | [[https://kaushalmodi.github.io/std_vector/][Documentation]] 8 | 9 | * What is this? 10 | Nim wrapper to map with the C++ ~std::vector~ library. 11 | 12 | /My goal is not to create a wrapper that wraps to 100% of the C++ 13 | library./ 14 | 15 | I will gradually update the wrapper as I find need for procs from the 16 | original library. 17 | * Install 18 | #+begin_example 19 | nimble install https://github.com/kaushalmodi/std_vector 20 | #+end_example 21 | * Requirements 22 | - Compile ~nim~ with the ~cpp~ backend. Example: 23 | #+begin_example 24 | nim cpp -r src/std_vector.nim 25 | #+end_example 26 | * References 27 | - https://en.cppreference.com/w/cpp/container/vector 28 | - https://forum.nim-lang.org/t/5787 29 | - https://github.com/BigEpsilon/nim-cppstl/blob/master/src/cppstl/vector.nim 30 | - https://github.com/numforge/agent-smith/blob/a2d9251e/third_party/std_cpp.nim#L23-L31 31 | - https://github.com/nim-lang/Nim/issues/9685#issue-379682147 32 | - https://forum.nim-lang.org/t/3401 33 | - https://nim-lang.github.io/Nim/manual.html#importcpp-pragma-importcpp-for-objects 34 | - https://nim-lang.github.io/Nim/manual.html#importcpp-pragma-importcpp-for-procs 35 | -------------------------------------------------------------------------------- /config.nims: -------------------------------------------------------------------------------- 1 | task pullConfig, "Fetch my global config.nims": 2 | exec("git submodule add -f -b master https://github.com/kaushalmodi/nim_config") 3 | when fileExists("nim_config/config.nims"): 4 | include "nim_config/config.nims" # This gives "nim test" and "nim docs" that's run on Travis 5 | -------------------------------------------------------------------------------- /src/config.nims: -------------------------------------------------------------------------------- 1 | when not compiles(nimVersion): 2 | const nimVersion = (major: NimMajor, minor: NimMinor, patch: NimPatch) 3 | 4 | when nimVersion >= (1, 3, 3): 5 | # https://github.com/nim-lang/Nim/commit/9502e39b634eea8e04f07ddc110b466387f42322 6 | switch("backend", "cpp") 7 | -------------------------------------------------------------------------------- /src/std_vector.nim: -------------------------------------------------------------------------------- 1 | ## :Author: Kaushal Modi 2 | ## :License: MIT 3 | ## 4 | ## Introduction 5 | ## ============ 6 | ## Nim wrapper to map with the C++ `std::vector `_ library. 7 | ## 8 | ## Source 9 | ## ====== 10 | ## `Repo link `_ 11 | 12 | when not defined(cpp): 13 | {.error: "This library needs to be compiled with the cpp backend.".} 14 | 15 | import std/[strformat] 16 | 17 | {.push header: "".} 18 | 19 | # https://forum.nim-lang.org/t/3401 20 | type 21 | Vector*[T] {.importcpp: "std::vector".} = object 22 | # https://nim-lang.github.io/Nim/manual.html#importcpp-pragma-importcpp-for-objects 23 | VectorIter*[T] {.importcpp: "std::vector<'0>::iterator".} = object 24 | VectorConstIter*[T] {.importcpp: "std::vector<'0>::const_iterator".} = object 25 | SizeType* = csize_t 26 | 27 | converter VectorIterToVectorConstIter*[T](x: VectorIter[T]): VectorConstIter[T] {.importcpp: "#".} 28 | ## Implicitly convert mutable C++ iterator to immutable C++ iterator. 29 | 30 | # https://nim-lang.github.io/Nim/manual.html#importcpp-pragma-importcpp-for-procs 31 | proc initVector*[T](): Vector[T] {.importcpp: "std::vector<'*0>()", constructor.} 32 | # https://github.com/numforge/agent-smith/blob/a2d9251e/third_party/std_cpp.nim#L23-L31 33 | proc initVector*[T](size: SizeType): Vector[T] {.importcpp: "std::vector<'*0>(#)", constructor.} 34 | 35 | proc len*(v: Vector): SizeType {.importcpp: "#.size()".} = 36 | ## Return the number of elements in the Vector. 37 | ## 38 | ## This has an alias proc `size`. 39 | ## 40 | ## https://en.cppreference.com/w/cpp/container/vector/size 41 | runnableExamples: 42 | var 43 | v = initVector[int]() 44 | doAssert v.size() == 0 45 | 46 | v.add(100) 47 | v.add(200) 48 | doAssert v.len() == 2 49 | 50 | proc empty*(v: Vector): bool {.importcpp: "empty".} = 51 | ## Check if the Vector is empty i.e. has zero elements. 52 | ## 53 | ## https://en.cppreference.com/w/cpp/container/vector/empty 54 | runnableExamples: 55 | var 56 | v = initVector[int]() 57 | doAssert v.empty() 58 | 59 | v.add(100) 60 | doAssert not v.empty() 61 | 62 | # https://github.com/numforge/agent-smith/blob/a2d9251e/third_party/std_cpp.nim#L23-L31 63 | proc `[]`*[T](v: Vector[T], idx: SizeType): var T {.importcpp: "#[#]".} = 64 | ## Return the reference to `v[idx]`. 65 | runnableExamples: 66 | var 67 | v = initVector[char]() 68 | v.add('a') 69 | v.add('b') 70 | v.add('c') 71 | 72 | v[1] = 'z' 73 | doAssert v[0] == 'a' 74 | doAssert v[1] == 'z' 75 | doAssert v[2] == 'c' 76 | 77 | proc first*[T](v: Vector[T]): var T {.importcpp: "front".} = 78 | ## Return the reference to the first element of the Vector. 79 | ## 80 | ## This has an alias proc `front`. 81 | ## 82 | ## https://en.cppreference.com/w/cpp/container/vector/front 83 | runnableExamples: 84 | var 85 | v = initVector[int]() 86 | 87 | v.add(100) 88 | v.add(200) 89 | doAssert v.first() == 100 90 | 91 | v.first() = 300 92 | doAssert v.first() == 300 93 | doAssert v.first() == v.front() 94 | 95 | proc last*[T](v: Vector[T]): var T {.importcpp: "back".} = 96 | ## Return the reference to the last element of the Vector. 97 | ## 98 | ## This has an alias proc `back`. 99 | ## 100 | ## https://www.cplusplus.com/reference/vector/vector/back/ 101 | runnableExamples: 102 | var 103 | v = initVector[int]() 104 | 105 | v.add(100) 106 | v.add(200) 107 | doAssert v.last() == 200 108 | 109 | v.last() = 300 110 | doAssert v.last() == 300 111 | doAssert v.last() == v.back() 112 | 113 | proc assign*[T](v: var Vector[T], num: SizeType, val: T) {.importcpp: "#.assign(@)".} = 114 | ## Return a Vector with `num` elements assigned to the specified value `val`. 115 | ## 116 | ## https://en.cppreference.com/w/cpp/container/vector/assign 117 | runnableExamples: 118 | var 119 | v: Vector[float] 120 | 121 | v.assign(5, 1.0) 122 | doAssert v.toSeq() == @[1.0, 1.0, 1.0, 1.0, 1.0] 123 | 124 | v.assign(2, 2.3) 125 | doAssert v.toSeq() == @[2.3, 2.3] 126 | 127 | # https://github.com/BigEpsilon/nim-cppstl/blob/de045c27dbbcf193081de5ea2b62f50751bf24fc/src/cppstl/vector.nim#L171 128 | # Relational operators 129 | proc `==`*[T](a: Vector[T], b: Vector[T]): bool {.importcpp: "# == #".} = 130 | ## Return `true` if the contents of lhs and rhs are equal, that is, 131 | ## they have the same number of elements and each element in lhs compares 132 | ## equal with the element in rhs at the same position. 133 | ## 134 | ## https://en.cppreference.com/w/cpp/container/vector/operator_cmp 135 | runnableExamples: 136 | let 137 | v1 = @[1, 2, 3].toVector() 138 | v2 = v1 139 | doAssert v1 == v2 140 | 141 | proc `!=`*[T](a: Vector[T], b: Vector[T]): bool {.importcpp: "# != #".} = 142 | ## Return `true` if the contents of lhs and rhs are not equal, that is, 143 | ## either they do not have the same number of elements, or one of the elements 144 | ## in lhs does not compare equal with the element in rhs at the same position. 145 | ## 146 | ## https://en.cppreference.com/w/cpp/container/vector/operator_cmp 147 | runnableExamples: 148 | let 149 | v1 = @[1, 2, 3].toVector() 150 | var 151 | v2 = v1 152 | v3 = v1 153 | v2.add(4) 154 | doAssert v2 != v1 155 | 156 | v3[0] = 100 157 | doAssert v3 != v1 158 | 159 | proc `<`*[T](a: Vector[T], b: Vector[T]): bool {.importcpp: "# < #".} = 160 | ## Return `true` if `a` is `lexicographically `_ 161 | ## less than `b`. 162 | ## 163 | ## https://en.cppreference.com/w/cpp/container/vector/operator_cmp 164 | runnableExamples: 165 | let 166 | v1 = @[1, 2, 3].toVector() 167 | var 168 | v2 = v1 169 | doAssert not (v1 < v2) 170 | 171 | v2.add(4) 172 | doAssert v1 < v2 173 | 174 | v2[2] = 0 175 | doAssert v2 < v1 176 | 177 | proc `<=`*[T](a: Vector[T], b: Vector[T]): bool {.importcpp: "# <= #".} = 178 | ## Return `true` if `a` is `lexicographically `_ 179 | ## less than or equal to `b`. 180 | ## 181 | ## https://en.cppreference.com/w/cpp/container/vector/operator_cmp 182 | runnableExamples: 183 | let 184 | v1 = @[1, 2, 3].toVector() 185 | var 186 | v2 = v1 187 | doAssert v1 <= v2 188 | 189 | v2.add(4) 190 | doAssert v1 <= v2 191 | 192 | v2[2] = 0 193 | doAssert v2 <= v1 194 | 195 | proc `>`*[T](a: Vector[T], b: Vector[T]): bool {.importcpp: "# > #".} = 196 | ## Return `true` if `a` is `lexicographically `_ 197 | ## greater than `b`. 198 | ## 199 | ## https://en.cppreference.com/w/cpp/container/vector/operator_cmp 200 | runnableExamples: 201 | let 202 | v1 = @[1, 2, 3].toVector() 203 | var 204 | v2 = v1 205 | doAssert not (v2 > v1) 206 | 207 | v2.add(4) 208 | doAssert v2 > v1 209 | 210 | v2[2] = 0 211 | doAssert v1 > v2 212 | 213 | proc `>=`*[T](a: Vector[T], b: Vector[T]): bool {.importcpp: "# >= #".} = 214 | ## Return `true` if `a` is `lexicographically `_ 215 | ## greater than or equal to `b`. 216 | ## 217 | ## https://en.cppreference.com/w/cpp/container/vector/operator_cmp 218 | runnableExamples: 219 | let 220 | v1 = @[1, 2, 3].toVector() 221 | var 222 | v2 = v1 223 | doAssert v2 >= v1 224 | 225 | v2.add(4) 226 | doAssert v2 >= v1 227 | 228 | v2[2] = 0 229 | doAssert v1 >= v2 230 | 231 | # https://github.com/BigEpsilon/nim-cppstl/blob/master/src/cppstl/private/utils.nim 232 | # Iterator Arithmetic 233 | proc `+`*[T: VectorIter|VectorConstIter](iter: T, offset: int): T {.importcpp: "# + #"} = 234 | ## Return an updated iterator pointing to the input iterator plus the specified `offset`. 235 | runnableExamples: 236 | var 237 | v = @[1.0, 2.0, 3.0].toVector() 238 | 239 | discard v.insert(v.cBegin()+1, 1.5) 240 | doAssert v.toSeq() == @[1.0, 1.5, 2.0, 3.0] 241 | 242 | discard v.insert(v.begin()+3, 2.5) 243 | doAssert v.toSeq() == @[1.0, 1.5, 2.0, 2.5, 3.0] 244 | 245 | proc `-`*[T: VectorIter|VectorConstIter](iter: T, offset: int): T {.importcpp: "# - #"} = 246 | ## Return an updated iterator pointing to the input iterator minus the specified `offset`. 247 | runnableExamples: 248 | var 249 | v = @[1.0, 2.0, 3.0].toVector() 250 | 251 | discard v.insert(v.cEnd()-1, 2.5) 252 | doAssert v.toSeq() == @[1.0, 2.0, 2.5, 3.0] 253 | 254 | discard v.insert(v.`end`()-3, 1.5) 255 | doAssert v.toSeq() == @[1.0, 1.5, 2.0, 2.5, 3.0] 256 | 257 | proc begin*[T](v: Vector[T]): VectorIter[T] {.importcpp: "begin".} = 258 | ## Return a mutable C++ iterator pointing to the beginning position of the Vector. 259 | ## 260 | ## https://www.cplusplus.com/reference/vector/vector/begin/ 261 | runnableExamples: 262 | var 263 | v = @[1, 2, 3].toVector() 264 | discard v.insert(v.begin(), 100) 265 | doAssert v.toSeq() == @[100, 1, 2, 3] 266 | 267 | proc cBegin*[T](v: Vector[T]): VectorConstIter[T] {.importcpp: "cbegin".} = 268 | ## Return an immutable C++ iterator pointing to the beginning position of the Vector. 269 | ## 270 | ## https://www.cplusplus.com/reference/vector/vector/begin/ 271 | runnableExamples: 272 | var 273 | v = @[1, 2, 3].toVector() 274 | discard v.insert(v.cBegin(), 100) 275 | doAssert v.toSeq() == @[100, 1, 2, 3] 276 | 277 | proc `end`*[T](v: Vector[T]): VectorIter[T] {.importcpp: "end".} = 278 | ## Return a mutable C++ iterator pointing to *after* the end position of the Vector. 279 | ## 280 | ## https://www.cplusplus.com/reference/vector/vector/end/ 281 | runnableExamples: 282 | var 283 | v = @[1, 2, 3].toVector() 284 | discard v.insert(v.`end`(), 100) 285 | doAssert v.toSeq() == @[1, 2, 3, 100] 286 | 287 | proc cEnd*[T](v: Vector[T]): VectorConstIter[T] {.importcpp: "cend".} = 288 | ## Return an immutable C++ iterator pointing to *after* the end position of the Vector. 289 | ## 290 | ## https://www.cplusplus.com/reference/vector/vector/end/ 291 | runnableExamples: 292 | var 293 | v = @[1, 2, 3].toVector() 294 | discard v.insert(v.cEnd(), 100) 295 | doAssert v.toSeq() == @[1, 2, 3, 100] 296 | 297 | 298 | # Modifiers 299 | 300 | proc add*[T](v: var Vector[T], elem: T){.importcpp: "#.push_back(#)".} = 301 | ## Append a new element to the end of the Vector. 302 | ## 303 | ## This has an alias proc `pushBack`. 304 | ## 305 | ## https://en.cppreference.com/w/cpp/container/vector/push_back 306 | runnableExamples: 307 | var 308 | v = initVector[int]() 309 | doAssert v.len() == 0 310 | 311 | v.add(100) 312 | v.pushBack(200) 313 | doAssert v.len() == 2 314 | 315 | proc popBack*[T](v: var Vector[T]) {.importcpp: "pop_back".} = 316 | ## Remove the last element of the Vector. 317 | ## This proc does not return anything. 318 | ## 319 | ## https://www.cplusplus.com/reference/vector/vector/pop_back/ 320 | runnableExamples: 321 | var 322 | v = initVector[int]() 323 | doAssert v.len() == 0 324 | 325 | v.add(100) 326 | doAssert v.len() == 1 327 | 328 | v.popBack() 329 | doAssert v.len() == 0 330 | 331 | proc insert*[T](v: var Vector[T], pos: VectorConstIter[T], val: T): VectorIter[T] {.importcpp: "insert".} = 332 | ## Insert an element before the specified position. 333 | runnableExamples: 334 | var 335 | v = @['a', 'b'].toVector() 336 | discard v.insert(v.cBegin(), 'c') 337 | doAssert v.toSeq() == @['c', 'a', 'b'] 338 | 339 | proc insert*[T](v: var Vector[T], pos: VectorConstIter[T], count: SizeType, val: T): VectorIter[T] {.importcpp: "insert".} = 340 | ## Insert `count` copies of element before the specified position. 341 | runnableExamples: 342 | var 343 | v = @['a', 'b'].toVector() 344 | discard v.insert(v.cBegin(), 3, 'c') 345 | doAssert v.toSeq() == @['c', 'c', 'c', 'a', 'b'] 346 | 347 | proc insert*[T](v: var Vector[T], pos, first, last: VectorConstIter[T]): VectorIter[T] {.importcpp: "insert".} = 348 | ## Insert elements from range `first` ..< `last` before the specified position. 349 | runnableExamples: 350 | let 351 | v1 = @['a', 'b'].toVector() 352 | var 353 | v2: Vector[char] 354 | discard v2.insert(v2.cBegin(), v1.cBegin(), v1.cEnd()) 355 | doAssert v2.toSeq() == @['a', 'b'] 356 | 357 | proc swap*[T](v1, v2: var Vector[T]) {.importcpp: "swap".} = 358 | ## Swap the contents of vectors `v1` and `v2`. 359 | ## 360 | ## https://en.cppreference.com/w/cpp/container/vector/swap 361 | runnableExamples: 362 | var 363 | v1 = @[1, 2, 3].toVector() 364 | v2 = @[7, 8, 9].toVector() 365 | v1.swap(v2) 366 | doAssert v1.toSeq() == @[7, 8, 9] 367 | doAssert v2.toSeq() == @[1, 2, 3] 368 | 369 | {.pop.} # {.push header: "".} 370 | 371 | 372 | # Aliases 373 | 374 | proc size*(v: Vector): SizeType {.inline.} = 375 | ## Alias for `len proc <#len,Vector>`_. 376 | v.len() 377 | 378 | proc pushBack*[T](v: var Vector[T]; elem: T) {.inline.} = 379 | ## Alias for `add proc <#add,Vector[T],T>`_. 380 | v.add(elem) 381 | 382 | proc front*[T](v: Vector[T]): T {.inline.} = 383 | ## Alias for `first proc <#first,Vector[T]>`_. 384 | v.first() 385 | 386 | proc back*[T](v: Vector[T]): T {.inline.} = 387 | ## Alias for `last proc <#last,Vector[T]>`_. 388 | v.last() 389 | 390 | 391 | # Other procs 392 | 393 | proc `[]=`*[T](v: var Vector[T], idx: SizeType, val: T) {.inline.} = 394 | ## Set the value at `v[idx]` to the specified value `val`. 395 | runnableExamples: 396 | var 397 | v = initVector[int](2) 398 | doAssert v.toSeq() == @[0, 0] 399 | 400 | v[0] = -1 401 | doAssert v.toSeq() == @[-1, 0] 402 | # 403 | # v[idx] = val # <-- This will not work because that will result in recursive calls of `[]=`. 404 | # So first get the elem using `[]`, then get its addr and then deref it. 405 | (unsafeAddr v[idx])[] = val 406 | 407 | 408 | # Iterators 409 | 410 | iterator items*[T](v: Vector[T]): T= 411 | ## Iterate over all the elements in Vector `v`. 412 | runnableExamples: 413 | var 414 | v: Vector[int] 415 | sum: int 416 | 417 | v.assign(3, 5) 418 | 419 | for elem in v: 420 | sum += elem 421 | doAssert sum == 15 422 | # 423 | for idx in 0.SizeType ..< v.len(): 424 | yield v[idx] 425 | 426 | iterator pairs*[T](v: Vector[T]): (SizeType, T) = 427 | ## Iterate over `(index, value)` for all the elements in Vector `v`. 428 | runnableExamples: 429 | var 430 | v: Vector[int] 431 | sum: int 432 | 433 | v.assign(3, 5) 434 | 435 | for idx, elem in v: 436 | sum += idx.int + elem 437 | doAssert sum == 18 438 | # 439 | for idx in 0.SizeType ..< v.len(): 440 | yield (idx, v[idx]) 441 | 442 | # To and from seq 443 | proc toSeq*[T](v: Vector[T]): seq[T] = 444 | ## Convert a Vector to a sequence. 445 | runnableExamples: 446 | var 447 | v: Vector[char] 448 | v.assign(3, 'k') 449 | 450 | doAssert v.toSeq() == @['k', 'k', 'k'] 451 | # 452 | for elem in v: 453 | result.add(elem) 454 | 455 | proc toVector*[T](s: openArray[T]): Vector[T] = 456 | ## Convert an array/sequence to a Vector. 457 | runnableExamples: 458 | let 459 | s = @[1, 2, 3] 460 | a = [1, 2, 3] 461 | 462 | doAssert s.toVector().toSeq() == s 463 | doAssert a.toVector().toSeq() == s 464 | # 465 | for elem in s: 466 | result.add(elem) 467 | 468 | # Display the content of a Vector 469 | # https://github.com/BigEpsilon/nim-cppstl/blob/de045c27dbbcf193081de5ea2b62f50751bf24fc/src/cppstl/vector.nim#L197 470 | proc `$`*[T](v: Vector[T]): string {.noinit.} = 471 | ## The `$` operator for Vector type variables. 472 | ## This is used internally when calling `echo` on a Vector type variable. 473 | runnableExamples: 474 | var 475 | v = initVector[int]() 476 | doAssert $v == "v[]" 477 | 478 | v.add(100) 479 | v.add(200) 480 | doAssert $v == "v[100, 200]" 481 | # 482 | if v.empty(): 483 | result = "v[]" 484 | else: 485 | result = "v[" 486 | for idx in 0.SizeType ..< v.size()-1: 487 | result.add($v[idx] & ", ") 488 | result.add($v.last() & "]") 489 | 490 | when isMainModule: 491 | import std/[unittest, sequtils] 492 | 493 | suite "constructor, size/len, empty": 494 | setup: 495 | var 496 | v1 = initVector[int]() 497 | v2 = initVector[int](10) 498 | 499 | test "size/len": 500 | check v1.size() == 0.SizeType 501 | check v2.len() == 10.SizeType 502 | 503 | test "empty": 504 | check v1.empty() == true 505 | check v2.empty() == false 506 | 507 | suite "push, pop": 508 | setup: 509 | var 510 | v = initVector[int]() 511 | 512 | test "push/add, pop, front/first, back/last": 513 | v.pushBack(100) 514 | check v.len() == 1.SizeType 515 | 516 | v.add(200) 517 | check v.len() == 2.SizeType 518 | 519 | v.popBack() 520 | check v.len() == 1.SizeType 521 | 522 | v.add(300) 523 | v.add(400) 524 | v.add(500) 525 | 526 | for idx in 0.SizeType ..< v.len(): 527 | echo &" v[{idx}] = {v[idx]}" 528 | 529 | check v.len() == 4.SizeType 530 | 531 | check v.first() == 100 532 | v.first() = 1 533 | check v.front() == 1 534 | 535 | check v.last() == 500 536 | v.last() = 5 537 | check v.back() == 5 538 | 539 | suite "iterators, $": 540 | setup: 541 | var 542 | v = initVector[cstring]() 543 | 544 | v.add("hi") 545 | v.add("there") 546 | v.add("bye") 547 | 548 | echo "Testing items iterator:" 549 | for elem in v: 550 | echo &" {elem}" 551 | echo "" 552 | 553 | echo "Testing pairs iterator:" 554 | for idx, elem in v: 555 | echo &" v[{idx}] = {elem}" 556 | 557 | test "$": 558 | check $v == "v[hi, there, bye]" 559 | 560 | suite "converting to/from a Vector/mutable sequence": 561 | setup: 562 | var 563 | s = @[1.1, 2.2, 3.3, 4.4, 5.5] 564 | v: Vector[float] 565 | 566 | test "mut seq -> mut Vector -> mut seq": 567 | v = s.toVector() 568 | check v.toSeq() == s 569 | 570 | 571 | suite "converting from an immutable sequence": 572 | setup: 573 | let 574 | s = @[1.1, 2.2, 3.3, 4.4, 5.5] 575 | var 576 | v: Vector[float] 577 | 578 | test "immut seq -> mut Vector -> mut seq": 579 | v = s.toVector() 580 | check v.toSeq() == s 581 | 582 | suite "converting array -> Vector -> sequence": 583 | setup: 584 | let 585 | a = [1.1, 2.2, 3.3, 4.4, 5.5] 586 | v = a.toVector() 587 | s = a.toSeq() 588 | 589 | test "immut array -> immut vector -> immut seq": 590 | check v.toSeq() == s 591 | 592 | suite "assign": 593 | setup: 594 | var 595 | v: Vector[char] 596 | 597 | test "assign": 598 | check v.len() == 0 599 | 600 | v.assign(4, '.') 601 | check v.toSeq() == @['.', '.', '.', '.'] 602 | 603 | v.assign(2, 'a') 604 | check v.toSeq() == @['a', 'a'] 605 | 606 | suite "set an element value": 607 | setup: 608 | var 609 | v = initVector[int](5) 610 | 611 | test "[]=": 612 | v[1] = 100 613 | v[3] = 300 614 | check v.toSeq() == @[0, 100, 0, 300, 0] 615 | 616 | suite "relational operators": 617 | setup: 618 | let 619 | v1 = @[1, 2, 3].toVector() 620 | 621 | test "==, <=, >=": 622 | let 623 | v2 = v1 624 | check v1 == v2 625 | check v1 <= v2 626 | check v1 >= v2 627 | 628 | test ">, >=": 629 | let 630 | v2 = @[1, 2, 4].toVector() 631 | check v2 > v1 632 | check v2 >= v1 633 | 634 | test ">, unequal vector lengths": 635 | let 636 | v2 = @[1, 2, 4].toVector() 637 | v3 = @[1, 2, 3, 0].toVector() 638 | check v3 > v1 639 | check v2 > v3 640 | 641 | test "<, <=": 642 | let 643 | v2 = @[1, 2, 4].toVector() 644 | check v1 < v2 645 | check v1 <= v2 646 | 647 | test "<, unequal vector lengths": 648 | let 649 | v2 = @[1, 2, 4].toVector() 650 | v3 = @[1, 2, 3, 0].toVector() 651 | check v1 < v3 652 | check v3 < v2 653 | 654 | suite "(c)begin, (c)end, insert": 655 | setup: 656 | var 657 | v = @[1, 2, 3].toVector() 658 | 659 | test "insert elem at the beginning": 660 | discard v.insert(v.cBegin(), 9) 661 | check v == @[9, 1, 2, 3].toVector() 662 | 663 | # Below, using .begin() instead of .cBegin() also 664 | # works.. because of the VectorIterToVectorConstIter converter. 665 | discard v.insert(v.begin(), 10) 666 | check v == @[10, 9, 1, 2, 3].toVector() 667 | 668 | test "insert elem at the end": 669 | discard v.insert(v.cEnd(), 9) 670 | check v == @[1, 2, 3, 9].toVector() 671 | 672 | # Below, using .`end`() instead of .cEnd() also 673 | # works.. because of the VectorIterToVectorConstIter converter. 674 | discard v.insert(v.`end`(), 10) 675 | check v == @[1, 2, 3, 9, 10].toVector() 676 | 677 | test "insert copies of a val": 678 | discard v.insert(v.cEnd(), 3, 111) 679 | check v == @[1, 2, 3, 111, 111, 111].toVector() 680 | 681 | test "insert elements from a Vector range": 682 | # Below copies the whole vector and appends to itself at the end. 683 | discard v.insert(v.cEnd(), v.cBegin(), v.cEnd()) 684 | check v == @[1, 2, 3, 1, 2, 3].toVector() 685 | 686 | # Below is a long-winded way to copy one Vector to another. 687 | var 688 | v2: Vector[int] 689 | discard v2.insert(v2.cEnd(), v.cBegin(), v.cEnd()) 690 | check v2 == v 691 | 692 | suite "iterator arithmetic": 693 | setup: 694 | var 695 | v = @[1, 2, 3].toVector() 696 | 697 | test "insert elem after the first element": 698 | discard v.insert(v.cBegin()+1, 9) 699 | check v == @[1, 9, 2, 3].toVector() 700 | 701 | test "insert elem before the last element": 702 | discard v.insert(v.cEnd()-1, 9) 703 | check v == @[1, 2, 9, 3].toVector() 704 | 705 | suite "two vectors": 706 | setup: 707 | var 708 | v1 = @['a', 'b', 'c'].toVector() 709 | v2 = @['w', 'x', 'y', 'z'].toVector() 710 | 711 | test "swap": 712 | v1.swap(v2) 713 | check v1 == @['w', 'x', 'y', 'z'].toVector() 714 | check v2 == @['a', 'b', 'c'].toVector() 715 | -------------------------------------------------------------------------------- /std_vector.nimble: -------------------------------------------------------------------------------- 1 | # Package 2 | 3 | version = "0.2.0" 4 | author = "Kaushal Modi" 5 | description = "Nim wrapper for C++ std::vector" 6 | license = "MIT" 7 | srcDir = "src" 8 | 9 | backend = "cpp" 10 | 11 | # Dependencies 12 | 13 | requires "nim >= 1.0.0" 14 | -------------------------------------------------------------------------------- /tests/test.nim: -------------------------------------------------------------------------------- 1 | import std/[os,strformat] 2 | 3 | template runCmd(cmd) = 4 | echo cmd 5 | doAssert execShellCmd(cmd) == 0 6 | 7 | proc main* = 8 | # xxx at least adding a few sanity checks would be nice 9 | const nim = getCurrentCompilerExe() 10 | runCmd fmt"{nim} doc src/std_vector.nim" 11 | main() 12 | --------------------------------------------------------------------------------