kdb_c_api/lib.rs
1//! **!!Notice!!** This crate was migrated to [kdbplus](https://crates.io/crates/kdbplus) which has IPC module as well.
2//!
3//! Rust crate mirroring the C API header file (`k.h`) for kdb+. The expected usage is to build a
4//! shared library for kdb+ in Rust.
5//!
6//! In order to avoid writing too large `unsafe` block leading to poor optimization, most of native C API functions were provided
7//! with a wrapper funtion with a bit of ergonomic safety and with intuitive implementation as a trait method. The only exceptions
8//! are `knk` and `k` which are using elipsis (`...`) as its argument. These functions are provided under `native` namespace with the other C API functions.
9//!
10//! # Note
11//! - This library is for kdb+ version >= 3.0.
12//! - Meangless C macros are excluded but accessors of an underlying array like `kC`, `kJ`, `kK` etc. are provided in Rust way.
13//!
14//! ## Examples
15//!
16//! The examples of using C API wrapper are included in `c_api_examples` folder. The examples are mirroring the examples in the document of `kdb_c_api` library and the functions are also used for simple tests of the library. The test is conducted in the `test.q` under `tests/` by loading the functions defined in a shared library built from the examples.
17//!
18//! Here are some examples:
19//!
20//! ### C API Style
21//!
22//! ```rust
23//! use kdb_c_api::*;
24//! use kdb_c_api::native::*;
25//!
26//! #[no_mangle]
27//! pub extern "C" fn create_symbol_list(_: K) -> K{
28//! unsafe{
29//! let mut list=ktn(qtype::SYMBOL as i32, 0);
30//! js(&mut list, ss(str_to_S!("Abraham")));
31//! js(&mut list, ss(str_to_S!("Isaac")));
32//! js(&mut list, ss(str_to_S!("Jacob")));
33//! js(&mut list, sn(str_to_S!("Josephine"), 6));
34//! list
35//! }
36//! }
37//!
38//! #[no_mangle]
39//! pub extern "C" fn catchy(func: K, args: K) -> K{
40//! unsafe{
41//! let result=ee(dot(func, args));
42//! if (*result).qtype == qtype::ERROR{
43//! println!("error: {}", S_to_str((*result).value.symbol));
44//! // Decrement reference count of the error object
45//! r0(result);
46//! KNULL
47//! }
48//! else{
49//! result
50//! }
51//! }
52//! }
53//!
54//! #[no_mangle]
55//! pub extern "C" fn dictionary_list_to_table() -> K{
56//! unsafe{
57//! let dicts=knk(3);
58//! let dicts_slice=dicts.as_mut_slice::<K>();
59//! for i in 0..3{
60//! let keys=ktn(qtype::SYMBOL as i32, 2);
61//! let keys_slice=keys.as_mut_slice::<S>();
62//! keys_slice[0]=ss(str_to_S!("a"));
63//! keys_slice[1]=ss(str_to_S!("b"));
64//! let values=ktn(qtype::INT as i32, 2);
65//! values.as_mut_slice::<I>()[0..2].copy_from_slice(&[i*10, i*100]);
66//! dicts_slice[i as usize]=xD(keys, values);
67//! }
68//! // Format list of dictionary as a table.
69//! // ([] a: 0 10 20i; b: 0 100 200i)
70//! k(0, str_to_S!("{[dicts] -1 _ dicts, (::)}"), dicts, KNULL)
71//! }
72//! }
73//! ```
74//!
75//! q can use these functions like this:
76//!
77//! ```q
78//! q)summon:`libc_api_examples 2: (`create_symbol_list; 1)
79//! q)summon[]
80//! `Abraham`Isaac`Jacob`Joseph
81//! q)`Abraham`Isaac`Jacob`Joseph ~ summon[]
82//! q)catchy: `libc_api_examples 2: (`catchy; 2);
83//! q)catchy[$; ("J"; "42")]
84//! 42
85//! q)catchy[+; (1; `a)]
86//! error: type
87//! q)unfortunate_fact: `libc_api_examples 2: (`dictionary_list_to_table; 1);
88//! q)unfortunate_fact[]
89//! a b
90//! ------
91//! 0 0
92//! 10 100
93//! 20 200
94//! ```
95//!
96//! ### Rust Style
97//!
98//! The examples below are written without `unsafe` code. You can see how comfortably breathing are the wrapped functions in the code.
99//!
100//! ```rust
101//! use kdb_c_api::*;
102//!
103//! #[no_mangle]
104//! pub extern "C" fn create_symbol_list2(_: K) -> K{
105//! let mut list=new_simple_list(qtype::SYMBOL, 0);
106//! list.push_symbol("Abraham").unwrap();
107//! list.push_symbol("Isaac").unwrap();
108//! list.push_symbol("Jacob").unwrap();
109//! list.push_symbol_n("Josephine", 6).unwrap();
110//! list
111//! }
112//!
113//! #[no_mangle]
114//! fn no_panick(func: K, args: K) -> K{
115//! let result=error_to_string(apply(func, args));
116//! if result.get_type() == qtype::ERROR{
117//! println!("FYI: {}", result.get_symbol().unwrap());
118//! // Decrement reference count of the error object which is no longer used.
119//! decrement_reference_count(result);
120//! KNULL
121//! }
122//! else{
123//! println!("success!");
124//! result
125//! }
126//! }
127//!
128//! #[no_mangle]
129//! pub extern "C" fn create_table2(_: K) -> K{
130//! // Build keys
131//! let keys=new_simple_list(qtype::SYMBOL, 2);
132//! let keys_slice=keys.as_mut_slice::<S>();
133//! keys_slice[0]=internalize(str_to_S!("time"));
134//! keys_slice[1]=internalize_n(str_to_S!("temperature_and_humidity"), 11);
135//!
136//! // Build values
137//! let values=new_simple_list(qtype::COMPOUND, 2);
138//! let time=new_simple_list(qtype::TIMESTAMP, 3);
139//! // 2003.10.10D02:24:19.167018272 2006.05.24D06:16:49.419710368 2008.08.12D23:12:24.018691392
140//! time.as_mut_slice::<J>().copy_from_slice(&[119067859167018272_i64, 201766609419710368, 271897944018691392]);
141//! let temperature=new_simple_list(qtype::FLOAT, 3);
142//! temperature.as_mut_slice::<F>().copy_from_slice(&[22.1_f64, 24.7, 30.5]);
143//! values.as_mut_slice::<K>().copy_from_slice(&[time, temperature]);
144//!
145//! flip(new_dictionary(keys, values))
146//! }
147//! ```
148//!
149//! And q code is here:
150//!
151//! ```q
152//! q)summon:`libc_api_examples 2: (`create_symbol_list2; 1)
153//! q)summon[]
154//! `Abraham`Isaac`Jacob`Joseph
155//! q)chill: `libc_api_examples 2: (`no_panick; 2);
156//! q)chill[$; ("J"; "42")]
157//! success!
158//! 42
159//! q)chill[+; (1; `a)]
160//! FYI: type
161//! q)climate_change: libc_api_examples 2: (`create_table2; 1);
162//! q)climate_change[]
163//! time temperature
164//! -----------------------------------------
165//! 2003.10.10D02:24:19.167018272 22.1
166//! 2006.05.24D06:16:49.419710368 24.7
167//! 2008.08.12D23:12:24.018691392 30.5
168//! ```
169
170#![allow(non_upper_case_globals)]
171#![allow(non_camel_case_types)]
172#![allow(non_snake_case)]
173
174//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
175// Load Libraries //
176//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
177
178use std::str;
179use std::ffi::CStr;
180use std::os::raw::{c_char, c_double, c_float, c_int, c_longlong, c_short, c_schar, c_uchar, c_void};
181use std::convert::TryInto;
182pub mod native;
183
184//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
185// Global Variables //
186//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
187
188pub mod qtype{
189 //! This module provides a list of q types. The motivation to contain them in a module is to
190 //! tie them up as related items rather than scattered values. Hence user should use these
191 //! indicators with `qtype::` prefix, e.g., `qtype::BOOL`.
192
193 use std::os::raw::c_schar;
194
195 /// Type indicator of q mixed list.
196 /// Access function: `kK`
197 pub const COMPOUND:c_schar=0;
198 /// Type indicator of q bool.
199 /// Access fucntion: `kG`
200 pub const BOOL:c_schar=1;
201 /// Type indicator of q GUID.
202 /// Access function: `kU`
203 pub const GUID:c_schar=2;
204 /// Type indicator of q byte
205 /// Access function: `kG`
206 pub const BYTE:c_schar=4;
207 /// Type indicator of q short.
208 /// Access function: `kH`
209 pub const SHORT:c_schar=5;
210 /// Type indicator of q int.
211 /// Access function: `kI`
212 pub const INT:c_schar=6;
213 /// Type indicator of q long.
214 /// Access function: `kJ`
215 pub const LONG:c_schar=7;
216 /// Type indicator of q real.
217 /// Access function: `kE`
218 pub const REAL:c_schar=8;
219 /// Type indicator of q float.
220 /// Access function: `kF`
221 pub const FLOAT:c_schar=9;
222 /// Type indicator of q char.
223 /// Access function: `kC`
224 pub const CHAR:c_schar=10;
225 /// Type indicator of q symbol.
226 /// Access function: `kS`
227 pub const SYMBOL:c_schar=11;
228 /// Type indicator of q timestamp.
229 /// Access function: `kJ`
230 pub const TIMESTAMP:c_schar=12;
231 /// Type indicator of q month.
232 /// Access function: `kI`
233 pub const MONTH:c_schar=13;
234 /// Type indicator of q date.
235 /// Access function: `kI`
236 pub const DATE:c_schar=14;
237 /// Type indicator of q datetime.
238 /// Access function: `kF`
239 pub const DATETIME:c_schar=15;
240 /// Type indicator of q timespan.
241 /// Access function: `kJ`
242 pub const TIMESPAN:c_schar=16;
243 /// Type indicator of q minute.
244 /// Access function: `kI`
245 pub const MINUTE:c_schar=17;
246 /// Type indicator of q second.
247 /// Access function: `kI`
248 pub const SECOND:c_schar=18;
249 /// Type indicator of q time.
250 /// Access function: `kI`
251 pub const TIME:c_schar=19;
252 /// Type indicator of q table.
253 /// `*(qstruct).k` is q dictionary.
254 pub const TABLE:c_schar=98;
255 /// Type indicator of q dictionary.
256 /// - `kK(x)[0]`: keys
257 /// - `kK(x)[1]`: values
258 pub const DICTIONARY:c_schar=99;
259 /// Type indicator of q foreign object.
260 pub const FOREIGN:c_schar=112;
261 /// Type indicator of q sorted dictionary
262 pub const SORTED_DICTIONARY:c_schar=127;
263 /// Type indicator of q error
264 pub const ERROR:c_schar=-128;
265 /// Type indicator of q general null
266 pub const NULL:c_schar=101;
267
268}
269
270pub mod qattribute{
271 //! This module provides a list of q attributes. The motivation to contain them in a module is to
272 //! tie them up as related items rather than scattered values. Hence user should use these
273 //! indicators with `qattribute::` prefix, e.g., `qattribute::UNIQUE`.
274
275 use std::os::raw::c_char;
276 /// Indicates no attribute is appended on the q object.
277 pub const NONE: c_char=0;
278 /// Sorted attribute, meaning that the q list is sorted in ascending order.
279 pub const SORTED: c_char=1;
280 /// Unique attribute, meaning that each element in the q list has a unique value within the list.
281 pub const UNIQUE: c_char=2;
282 /// Parted attribute, meaning that all the elements with the same value in the q object appear in a chunk.
283 pub const PARTED: c_char=3;
284 /// Grouped attribute, meaning that the elements of the q list are grouped with their indices by values implicitly.
285 pub const GROUPED: c_char=4;
286
287}
288
289/// `K` nullptr. This value is used as general null returned value (`(::)`).
290/// # Example
291/// ```
292/// use kdb_c_api::*;
293///
294/// #[no_mangle]
295/// pub extern "C" fn vanity(_: K) -> K{
296/// println!("Initialized something, probably it is your mindset.");
297/// KNULL
298/// }
299/// ```
300pub const KNULL:K=0 as K;
301
302//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
303// Macros //
304//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
305
306//%% Utility %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
307
308/// Convert `&str` to `S` (null-terminated character array).
309/// # Example
310/// ```no_run
311/// use kdb_c_api::*;
312///
313/// #[no_mangle]
314/// pub extern "C" fn pingpong(_: K) -> K{
315/// unsafe{native::k(0, str_to_S!("ping"), new_int(77), KNULL)}
316/// }
317/// ```
318/// ```q
319/// q)ping:{[int] `$string[int], "_pong!!"}
320/// q)pingpong: `libc_api_examples 2: (`pingpong; 1);
321/// q)pingpong[]
322/// `77_pong!!
323/// ```
324/// # Note
325/// This macro cannot be created as a function due to freeing resource of Rust (not sure).
326#[macro_export]
327macro_rules! str_to_S {
328 ($string: expr) => {
329 [$string.as_bytes(), &[b'\0']].concat().as_mut_ptr() as S
330 };
331}
332
333//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
334// Structs //
335//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
336
337//%% Alias %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
338
339/// `char*` in C. Also used to access symbol of q.
340pub type S = *mut c_char;
341/// `const char*` in C.
342pub type const_S = *const c_char;
343/// `char` in C. Also used to access char of q.
344pub type C = c_char;
345/// `unsigned char` in C. Also used to access byte of q.
346pub type G = c_uchar;
347/// `i16` in C. Also used to access short of q.
348pub type H = c_short;
349/// `i32` in C. Also used to access int and compatible types (month, date, minute, second and time) of q.
350pub type I = c_int;
351/// `i64` in C. Also used to access long and compatible types (timestamp and timespan) of q.
352pub type J = c_longlong;
353/// `f32` in C. Also used to access real of q.
354pub type E = c_float;
355/// `f64` in C. Also used to access float and datetime of q.
356pub type F = c_double;
357/// `void` in C.
358pub type V = c_void;
359
360//%% U %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
361
362/// Struct representing 16-bytes GUID.
363#[derive(Clone, Copy, Debug)]
364#[repr(C)]
365pub struct U{
366 pub guid: [G; 16]
367}
368
369//%% K %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
370
371/// Underlying list value of q object.
372/// # Note
373/// Usually this struct does not need to be accessed this struct directly unless user wants to
374/// access via a raw pointer for non-trivial stuff.
375#[derive(Clone, Copy, Debug)]
376#[repr(C)]
377pub struct k0_list_info{
378 /// Length of the list.
379 pub n: J,
380 /// Pointer referring to the head of the list. This pointer will be interpreted
381 /// as various types when accessing `K` object to edit the list with
382 /// [`as_mut_slice`](trait.KUtility.html#tymethod.as_mut_slice).
383 pub G0: [G; 1]
384}
385
386/// Underlying atom value of q object.
387/// # Note
388/// Usually this struct does not need to be accessed directly unless user wants to
389/// access via a raw pointer for non-trivial stuff.
390#[derive(Clone, Copy)]
391#[repr(C)]
392pub union k0_inner{
393 /// Byte type holder.
394 pub byte: G,
395 /// Short type holder.
396 pub short: H,
397 /// Int type holder.
398 pub int: I,
399 /// Long type older.
400 pub long: J,
401 /// Real type holder.
402 pub real: E,
403 /// Float type holder.
404 pub float: F,
405 /// Symbol type holder.
406 pub symbol: S,
407 /// Table type holder.
408 pub table: *mut k0,
409 /// List type holder.
410 pub list: k0_list_info
411}
412
413/// Underlying struct of `K` object.
414#[repr(C)]
415#[derive(Clone, Copy)]
416pub struct k0{
417 /// For internal usage.
418 pub m: c_schar,
419 /// For internal usage.
420 pub a: c_schar,
421 /// Type indicator.
422 pub qtype: c_schar,
423 /// Attribute of list.
424 pub attribute: C,
425 /// Reference count of the object.
426 pub refcount: I,
427 /// Underlying value.
428 pub value: k0_inner
429}
430
431/// Struct representing q object.
432pub type K=*mut k0;
433
434//%% KList %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
435
436pub trait KUtility{
437 /// Derefer `K` as a mutable slice of the specified type. The supported types are:
438 /// - `G`: Equivalent to C API macro `kG`.
439 /// - `H`: Equivalent to C API macro `kH`.
440 /// - `I`: Equivalent to C API macro `kI`.
441 /// - `J`: Equivalent to C API macro `kJ`.
442 /// - `E`: Equivalent to C API macro `kE`.
443 /// - `F`: Equivalent to C API macro `kF`.
444 /// - `C`: Equivalent to C API macro `kC`.
445 /// - `S`: Equivalent to C API macro `kS`.
446 /// - `K`: Equivalent to C API macro `kK`.
447 /// # Example
448 /// ```
449 /// use kdb_c_api::*;
450 ///
451 /// #[no_mangle]
452 /// pub extern "C" fn modify_long_list_a_bit(long_list: K) -> K{
453 /// if long_list.len() >= 2{
454 /// // Derefer as a mutable i64 slice.
455 /// long_list.as_mut_slice::<J>()[1]=30000_i64;
456 /// // Increment the counter to reuse on q side.
457 /// increment_reference_count(long_list)
458 /// }
459 /// else{
460 /// new_error("this list is not long enough. how ironic...\0")
461 /// }
462 /// }
463 /// ```
464 /// ```q
465 /// q)ironic: `libc_api_examples 2: (`modify_long_list_a_bit; 1);
466 /// q)list:1 2 3;
467 /// q)ironic list
468 /// 1 30000 3
469 /// q)ironic enlist 1
470 /// ```
471 /// # Note
472 /// Intuitively the parameter should be `&mut self` but it restricts a manipulating
473 /// `K` objects in the form of slice simultaneously. As copying a pointer is not
474 /// an expensive operation, using `self` should be fine.
475 fn as_mut_slice<'a, T>(self) -> &'a mut[T];
476
477 /// Get an underlying q byte.
478 /// # Example
479 /// ```no_run
480 /// use kdb_c_api::*;
481 ///
482 /// #[no_mangle]
483 /// pub extern "C" fn print_bool(atom: K) -> K{
484 /// match atom.get_bool(){
485 /// Ok(boolean) => {
486 /// println!("bool: {}", boolean);
487 /// KNULL
488 /// },
489 /// Err(error) => new_error(error)
490 /// }
491 /// }
492 /// ```
493 /// ```q
494 /// q)print_boole: `libc_api_examples 2: (`print_bool; 1);
495 /// q)print_bool[1b]
496 /// bool: true
497 /// ```
498 fn get_bool(&self) -> Result<bool, &'static str>;
499
500 /// Get an underlying q byte.
501 /// # Example
502 /// ```no_run
503 /// use kdb_c_api::*;
504 ///
505 /// #[no_mangle]
506 /// pub extern "C" fn print_guid(atom: K) -> K{
507 /// match atom.get_guid(){
508 /// Ok(guid) => {
509 /// let strguid=guid.iter().map(|b| format!("{:02x}", b)).collect::<String>();
510 /// println!("GUID: {}-{}-{}-{}-{}", &strguid[0..4], &strguid[4..6], &strguid[6..8], &strguid[8..10], &strguid[10..16]);
511 /// KNULL
512 /// },
513 /// Err(error) => new_error(error)
514 /// }
515 /// }
516 /// ```
517 /// ```q
518 /// q)print_guid: `libc_api_examples 2: (`print_guid; 1);
519 /// q)guid: first 1?0Ng;
520 /// q)print_guid[guid]
521 /// GUID: 8c6b-8b-64-68-156084
522 /// ```
523 fn get_guid(&self) -> Result<[u8; 16], &'static str>;
524
525 /// Get an underlying q byte.
526 /// # Example
527 /// ```no_run
528 /// use kdb_c_api::*;
529 ///
530 /// #[no_mangle]
531 /// pub extern "C" fn print_byte(atom: K) -> K{
532 /// match atom.get_byte(){
533 /// Ok(byte) => {
534 /// println!("byte: {:#4x}", byte);
535 /// KNULL
536 /// },
537 /// Err(error) => new_error(error)
538 /// }
539 /// }
540 /// ```
541 /// ```q
542 /// q)print_byte: `libc_api_examples 2: (`print_byte; 1);
543 /// q)print_byte[0xc4]
544 /// byte: 0xc4
545 /// ```
546 fn get_byte(&self) -> Result<u8, &'static str>;
547
548 /// Get an underlying q short.
549 /// # Example
550 /// ```no_run
551 /// use kdb_c_api::*;
552 ///
553 /// #[no_mangle]
554 /// pub extern "C" fn print_short(atom: K) -> K{
555 /// match atom.get_short(){
556 /// Ok(short) => {
557 /// println!("short: {}", short);
558 /// KNULL
559 /// },
560 /// Err(error) => new_error(error)
561 /// }
562 /// }
563 /// ```
564 /// ```q
565 /// q)print_short: `libc_api_examples 2: (`print_short; 1);
566 /// q)print_short[10h]
567 /// short: 10
568 /// ```
569 fn get_short(&self) -> Result<i16, &'static str>;
570
571 /// Get an underlying q int.
572 /// # Example
573 /// ```no_run
574 /// use kdb_c_api::*;
575 ///
576 /// #[no_mangle]
577 /// pub extern "C" fn print_int(atom: K) -> K{
578 /// match atom.get_int(){
579 /// Ok(int) => {
580 /// println!("int: {}", int);
581 /// KNULL
582 /// },
583 /// Err(error) => new_error(error)
584 /// }
585 /// }
586 /// ```
587 /// ```q
588 /// q)print_int: `libc_api_examples 2: (`print_int; 1);
589 /// q)print_int[03:57:20]
590 /// int: 14240
591 /// ```
592 fn get_int(&self) -> Result<i32, &'static str>;
593
594 /// Get an underlying q long.
595 /// # Example
596 /// ```no_run
597 /// use kdb_c_api::*;
598 ///
599 /// #[no_mangle]
600 /// pub extern "C" fn print_long(atom: K) -> K{
601 /// match atom.get_long(){
602 /// Ok(long) => {
603 /// println!("long: {}", long);
604 /// KNULL
605 /// },
606 /// Err(error) => new_error(error)
607 /// }
608 /// }
609 /// ```
610 /// ```q
611 /// q)print_long: `libc_api_examples 2: (`print_long; 1);
612 /// q)print_long[2000.01.01D12:00:00.123456789]
613 /// long: 43200123456789
614 /// ```
615 fn get_long(&self) -> Result<i64, &'static str>;
616
617 /// Get an underlying q real.
618 /// # Example
619 /// ```no_run
620 /// use kdb_c_api::*;
621 ///
622 /// #[no_mangle]
623 /// pub extern "C" fn print_real(atom: K) -> K{
624 /// match atom.get_real(){
625 /// Ok(real) => {
626 /// println!("real: {}", real);
627 /// KNULL
628 /// },
629 /// Err(error) => new_error(error)
630 /// }
631 /// }
632 /// ```
633 /// ```q
634 /// q)print_real: `libc_api_examples 2: (`print_real; 1);
635 /// q)print_real[193810.32e]
636 /// real: 193810.31
637 /// ```
638 fn get_real(&self) -> Result<f32, &'static str>;
639
640 /// Get an underlying q float.
641 /// # Example
642 /// ```no_run
643 /// use kdb_c_api::*;
644 ///
645 /// #[no_mangle]
646 /// pub extern "C" fn print_float(atom: K) -> K{
647 /// match atom.get_float(){
648 /// Ok(float) => {
649 /// println!("float: {:.8}", float);
650 /// KNULL
651 /// },
652 /// Err(error) => new_error(error)
653 /// }
654 /// }
655 /// ```
656 /// ```q
657 /// q)print_float: `libc_api_examples 2: (`print_float; 1);
658 /// q)print_float[2002.01.12T10:03:45.332]
659 /// float: 742.41927468
660 /// ```
661 fn get_float(&self) -> Result<f64, &'static str>;
662
663 /// Get an underlying q char.
664 /// # Example
665 /// ```no_run
666 /// use kdb_c_api::*;
667 ///
668 /// #[no_mangle]
669 /// pub extern "C" fn print_char(atom: K) -> K{
670 /// match atom.get_char(){
671 /// Ok(character) => {
672 /// println!("char: \"{}\"", character);
673 /// KNULL
674 /// },
675 /// Err(error) => new_error(error)
676 /// }
677 /// }
678 /// ```
679 /// ```q
680 /// q)print_char: `libc_api_examples 2: (`print_char; 1);
681 /// q)print_char["k"]
682 /// char: "k"
683 /// ```
684 fn get_char(&self) -> Result<char, &'static str>;
685
686 /// Get an underlying q symbol.
687 /// # Example
688 /// ```no_run
689 /// use kdb_c_api::*;
690 ///
691 /// #[no_mangle]
692 /// pub extern "C" fn print_symbol2(atom: K) -> K{
693 /// match atom.get_symbol(){
694 /// Ok(symbol) => {
695 /// println!("symbol: `{}", symbol);
696 /// KNULL
697 /// },
698 /// Err(error) => new_error(error)
699 /// }
700 /// }
701 /// ```
702 /// ```q
703 /// q)print_symbol2: `libc_api_examples 2: (`print_symbol2; 1);
704 /// q)print_symbol2[`locust]
705 /// symbol: `locust
706 /// ```
707 fn get_symbol(&self) -> Result<&str, &'static str>;
708
709 /// Get an underlying q string as `&str`.
710 /// # Example
711 /// ```no_run
712 /// use kdb_c_api::*;
713 ///
714 /// #[no_mangle]
715 /// pub extern "C" fn print_string(string: K) -> K{
716 /// match string.get_str(){
717 /// Ok(string_) => {
718 /// println!("string: \"{}\"", string_);
719 /// KNULL
720 /// },
721 /// Err(error) => new_error(error)
722 /// }
723 /// }
724 /// ```
725 /// ```q
726 /// q)print_string: `libc_api_examples 2: (`print_string; 1);
727 /// q)print_string["gnat"]
728 /// string: "gnat"
729 /// ```
730 fn get_str(&self) -> Result<&str, &'static str>;
731
732 /// Get an underlying q string as `String`.
733 /// # Example
734 /// ```no_run
735 /// use kdb_c_api::*;
736 ///
737 /// #[no_mangle]
738 /// pub extern "C" fn print_string2(string: K) -> K{
739 /// match string.get_string(){
740 /// Ok(string_) => {
741 /// println!("string: \"{}\"", string_);
742 /// KNULL
743 /// },
744 /// Err(error) => new_error(error)
745 /// }
746 /// }
747 /// ```
748 /// ```q
749 /// q)print_string: `libc_api_examples 2: (`print_string; 1);
750 /// q)print_string["grasshopper"]
751 /// string: "grasshopper"
752 /// ```
753 fn get_string(&self) -> Result<String, &'static str>;
754
755 /// Get a flipped underlying q table as `K` (dictionary).
756 /// # Example
757 /// ```no_run
758 /// use kdb_c_api::*;
759 ///
760 /// #[no_mangle]
761 /// pub extern "C" fn hidden_key(table: K) -> K{
762 /// match table.get_dictionary(){
763 /// Ok(dictionary) => dictionary.as_mut_slice::<K>()[0].q_ipc_encode(3).unwrap(),
764 /// Err(error) => new_error(error)
765 /// }
766 /// }
767 /// ```
768 /// ```q
769 /// q)perceive_the_man: `libc_api_examples 2: (`hidden_key; 1);
770 /// q)perceive_the_man ([] t: `timestamp$.z.p+1e9*til 9; chr:"ljppkgfgs"; is: 7 8 12 14 21 316 400 1000 6000i)
771 /// 0x01000000170000000b0003000000740063687200697300
772 /// ```
773 /// # Note
774 /// This method is provided because the ony way to examine the value of table type is to access the underlying dictionary (flipped table).
775 /// Also when some serialization is necessary for a table, you can reuse a serializer for a dictionary if it is already provided. Actually
776 /// when q serialize a table object with `-8!` (q function) or `b9` (C code), it just serializes the underlying dictionary with an additional
777 /// marker indicating a table type.
778 fn get_dictionary(&self) -> Result<K, &'static str>;
779
780 /// Get an attribute of a q object.
781 /// # Example
782 /// ```no_run
783 /// use kdb_c_api::*;
784 ///
785 /// #[no_mangle]
786 /// pub extern "C" fn murmur(list: K) -> K{
787 /// match list.get_attribute(){
788 /// qattribute::SORTED => {
789 /// new_string("Clean")
790 /// },
791 /// qattribute::UNIQUE => {
792 /// new_symbol("Alone")
793 /// },
794 /// _ => KNULL
795 /// }
796 /// }
797 /// ```
798 fn get_attribute(&self) -> C;
799
800 /// Get a reference count of a q object.
801 fn get_refcount(&self) -> I;
802
803 /// Append a q list object to a q list.
804 /// Returns a pointer to the (potentially reallocated) `K` object.
805 /// ```no_run
806 /// use kdb_c_api::*;
807 ///
808 /// #[no_mangle]
809 /// pub extern "C" fn concat_list2(mut list1: K, list2: K) -> K{
810 /// if let Err(err) = list1.append(list2){
811 /// new_error(err)
812 /// }
813 /// else{
814 /// increment_reference_count(list1)
815 /// }
816 /// }
817 /// ```
818 /// ```q
819 /// q)plunder: `libc_api_examples 2: (`concat_list2; 2);
820 /// q)plunder[(::; `metals; `fire); ("clay"; 316)]
821 /// ::
822 /// `metals
823 /// `fire
824 /// "clay"
825 /// 316
826 /// q)plunder[1 2 3; 4 5]
827 /// 1 2 3 4 5
828 /// q)plunder[`a`b`c; `d`e]
829 /// `a`b`c`d`e
830 /// ```
831 fn append(&mut self, list: K)->Result<K, &'static str>;
832
833 /// Add a q object to a q compound list.
834 /// Returns a pointer to the (potentially reallocated) `K` object.
835 /// # Example
836 /// ```no_run
837 /// use kdb_c_api::*;
838 ///
839 /// #[no_mangle]
840 /// pub extern "C" fn create_compound_list(int: K) -> K{
841 /// let mut list=new_simple_list(qtype::COMPOUND, 0);
842 /// for i in 0..5{
843 /// list.push(new_long(i)).unwrap();
844 /// }
845 /// list.push(increment_reference_count(int)).unwrap();
846 /// list
847 /// }
848 /// ```
849 /// ```q
850 /// q)nums: `libc_api_examples 2: (`create_compound_list2; 1);
851 /// q)nums[5i]
852 /// 0
853 /// 1
854 /// 2
855 /// 3
856 /// 4
857 /// 5i
858 /// ```
859 /// # Note
860 /// In this example we did not allocate an array as `new_simple_list(qtype::COMPOUND, 0)` to use `push`.
861 /// As `new_simple_list` initializes the internal list size `n` with its argument, preallocating memory with `new_simple_list` and
862 /// then using `push` will crash. If you want to allocate a memory in advance, you can substitute a value
863 /// after converting the q list object into a slice with [`as_mut_slice`](rait.KUtility.html#tymethod.as_mut_slice).
864 fn push(&mut self, atom: K)->Result<K, &'static str>;
865
866 /// Add a raw value to a q simple list and returns a pointer to the (potentially reallocated) `K` object.
867 /// # Example
868 /// ```no_run
869 /// use kdb_c_api::*;
870 ///
871 /// #[no_mangle]
872 /// pub extern "C" fn create_simple_list2(_: K) -> K{
873 /// let mut list=new_simple_list(qtype::DATE, 0);
874 /// for i in 0..5{
875 /// list.push_raw(i).unwrap();
876 /// }
877 /// list
878 /// }
879 /// ```
880 /// ```q
881 /// q)simple_is_the_best: `lic_api_example 2: (`create_simple_list2; 1);
882 /// q)simple_is_the_best[]
883 /// 2000.01.01 2000.01.02 2000.01.03 2000.01.04 2000.01.05
884 /// ```
885 /// # Note
886 /// - Concrete type of `T` is not checked. Its type must be either of `I`, `J` and `F` and it must be compatible
887 /// with the list type. For example, timestamp list requires `J` type atom.
888 /// - For symbol list, use [`push_symbol`](#fn.push_symbol) or [`push_symbol_n`](#fn.push_symbol_n).
889 fn push_raw<T>(&mut self, atom: T)->Result<K, &'static str>;
890
891 /// Add an internalized char array to symbol list.
892 /// Returns a pointer to the (potentially reallocated) `K` object.
893 /// # Example
894 /// ```no_run
895 /// use kdb_c_api::*;
896 ///
897 /// #[no_mangle]
898 /// pub extern "C" fn create_symbol_list2(_: K) -> K{
899 /// let mut list=new_simple_list(qtype::SYMBOL, 0);
900 /// list.push_symbol("Abraham").unwrap();
901 /// list.push_symbol("Isaac").unwrap();
902 /// list.push_symbol("Jacob").unwrap();
903 /// list.push_symbol_n("Josephine", 6).unwrap();
904 /// list
905 /// }
906 /// ```
907 /// ```q
908 /// q)summon:`libc_api_examples 2: (`create_symbol_list2; 1)
909 /// q)summon[]
910 /// `Abraham`Isaac`Jacob`Joseph
911 /// q)`Abraham`Isaac`Jacob`Joseph ~ summon[]
912 /// 1b
913 /// ```
914 /// # Note
915 /// In this example we did not allocate an array as `new_simple_list(qtype::SYMBOL as I, 0)` to use `push_symbol`.
916 /// As `new_simple_list` initializes the internal list size `n` with its argument, preallocating memory with `new_simple_list`
917 /// and then using `push_symbol` will crash. If you want to allocate a memory in advance, you can substitute a value
918 /// after converting the q list object into a slice with [`as_mut_slice`](trait.KUtility.html#tymethod.as_mut_slice).
919 fn push_symbol(&mut self, symbol: &str)->Result<K, &'static str>;
920
921 /// Add an internalized char array to symbol list.
922 /// Returns a pointer to the (potentially reallocated) `K` object.
923 /// # Example
924 /// See the example of [`push_symbol`](#fn.push_symbol).
925 fn push_symbol_n(&mut self, symbol: &str, n: I)->Result<K, &'static str>;
926
927 /// Get a length of the list. More specifically, a value of `k0.value.list.n` for list types.
928 /// Otherwise 2 for table and 1 for atom and null.
929 /// # Example
930 /// ```no_run
931 /// use kdb_c_api::*;
932 ///
933 /// #[no_mangle]
934 /// pub extern "C" fn numbers(obj: K) -> K{
935 /// let count=format!("{} people are in numbers", obj.len());
936 /// new_string(&count)
937 /// }
938 /// ```
939 /// ```q
940 /// q)census: `libc_api_examples 2: (`numbers; 1);
941 /// q)census[(::)]
942 /// "1 people are in numbers"
943 /// q)census[til 4]
944 /// "4 people are in numbers"
945 /// q)census[`a`b!("many"; `split`asunder)]
946 /// "2 people are in numbers"
947 /// q)census[([] id: til 1000)]
948 /// "1000 people are in numbers"
949 /// ```
950 fn len(&self) -> i64;
951
952 /// Get a type of `K` object.
953 fn get_type(&self) -> i8;
954
955 /// Set a type of `K` object.
956 /// # Example
957 /// See the example of [`load_as_q_function](fn.load_as_q_function.html).
958 fn set_type(&self, qtype: i8);
959
960 /// Serialize q object and return serialized q byte list object on success: otherwise null.
961 /// Mode is either of:
962 /// - -1: Serialize within the same process.
963 /// - 1: retain enumerations, allow serialization of timespan and timestamp: Useful for passing data between threads
964 /// - 2: unenumerate, allow serialization of timespan and timestamp
965 /// - 3: unenumerate, compress, allow serialization of timespan and timestamp
966 /// # Example
967 /// ```no_run
968 /// use kdb_c_api::*;
969 ///
970 /// #[no_mangle]
971 /// pub extern "C" fn encrypt(object: K)->K{
972 /// match object.q_ipc_encode(3){
973 /// Ok(bytes) => bytes,
974 /// Err(error) => new_error(error)
975 /// }
976 /// }
977 /// ```
978 /// ```q
979 /// q)disguise: `libc_api_examples 2: (`encrypt; 1);
980 /// q)list: (til 3; "abc"; 2018.02.18D04:30:00.000000000; `revive);
981 /// q)disguise list
982 /// 0x010000004600000000000400000007000300000000000000000000000100000000000000020..
983 /// ```
984 fn q_ipc_encode(&self, mode: I) -> Result<K, &'static str>;
985
986 /// Deserialize a bytes into q object.
987 /// # Example
988 /// ```no_run
989 /// use kdb_c_api::*;
990 ///
991 /// #[no_mangle]
992 /// pub extern "C" fn decrypt(bytes: K)->K{
993 /// match bytes.q_ipc_decode(){
994 /// Ok(object) => object,
995 /// Err(error) => new_error(error)
996 /// }
997 /// }
998 /// ```
999 /// ```q
1000 /// q)uncover: `libc_api_examples 2: (`decrypt; 1);
1001 /// q)uncover -8!"What is the purpose of CREATION?"
1002 /// "What is the purpose of CREATION?"
1003 /// ```
1004 fn q_ipc_decode(&self) -> Result<K, &'static str>;
1005}
1006
1007//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
1008// Implementation //
1009//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
1010
1011//%% U %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
1012
1013impl U{
1014 /// Create 16-byte GUID object.
1015 pub fn new(guid: [u8; 16]) -> Self{
1016 U{guid:guid}
1017 }
1018}
1019
1020//%% K %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
1021
1022unsafe impl Send for k0_inner{}
1023unsafe impl Send for k0{}
1024
1025impl KUtility for K{
1026 #[inline]
1027 fn as_mut_slice<'a, T>(self) -> &'a mut[T]{
1028 unsafe{
1029 std::slice::from_raw_parts_mut((*self).value.list.G0.as_mut_ptr() as *mut T, (*self).value.list.n as usize)
1030 }
1031 }
1032
1033 #[inline]
1034 fn get_bool(&self) -> Result<bool, &'static str>{
1035 match unsafe{(**self).qtype}.saturating_mul(-1){
1036 qtype::BOOL => Ok(unsafe{(**self).value.byte != 0}),
1037 _ => Err("not a bool\0")
1038 }
1039 }
1040
1041 #[inline]
1042 fn get_guid(&self) -> Result<[u8; 16], &'static str>{
1043 match unsafe{(**self).qtype}.saturating_mul(-1){
1044 qtype::GUID => {
1045 Ok(unsafe{std::slice::from_raw_parts((**self).value.list.G0.as_ptr(), 16)}.try_into().unwrap())
1046 },
1047 _ => Err("not a GUID\0")
1048 }
1049 }
1050
1051 #[inline]
1052 fn get_byte(&self) -> Result<u8, &'static str>{
1053 match unsafe{(**self).qtype}.saturating_mul(-1){
1054 qtype::BYTE => Ok(unsafe{(**self).value.byte}),
1055 _ => Err("not a byte\0")
1056 }
1057 }
1058
1059 #[inline]
1060 fn get_short(&self) -> Result<i16, &'static str>{
1061 match unsafe{(**self).qtype}.saturating_mul(-1){
1062 qtype::SHORT => Ok(unsafe{(**self).value.short}),
1063 _ => Err("not a short\0")
1064 }
1065 }
1066
1067 #[inline]
1068 fn get_int(&self) -> Result<i32, &'static str>{
1069 match unsafe{(**self).qtype}.saturating_mul(-1){
1070 qtype::INT | qtype::MONTH | qtype::DATE | qtype::MINUTE | qtype::SECOND | qtype::TIME => Ok(unsafe{(**self).value.int}),
1071 _ => Err("not an int\0")
1072 }
1073 }
1074
1075 #[inline]
1076 fn get_long(&self) -> Result<i64, &'static str>{
1077 match unsafe{(**self).qtype}.saturating_mul(-1){
1078 qtype::LONG | qtype::TIMESTAMP | qtype::TIMESPAN => Ok(unsafe{(**self).value.long}),
1079 _ => Err("not a long\0")
1080 }
1081 }
1082
1083 #[inline]
1084 fn get_real(&self) -> Result<f32, &'static str>{
1085 match unsafe{(**self).qtype}.saturating_mul(-1){
1086 qtype::REAL => Ok(unsafe{(**self).value.real}),
1087 _ => Err("not a real\0")
1088 }
1089 }
1090
1091 #[inline]
1092 fn get_float(&self) -> Result<f64, &'static str>{
1093 match unsafe{(**self).qtype}.saturating_mul(-1){
1094 qtype::FLOAT | qtype::DATETIME => Ok(unsafe{(**self).value.float}),
1095 _ => Err("not a float\0")
1096 }
1097 }
1098
1099 #[inline]
1100 fn get_char(&self) -> Result<char, &'static str>{
1101 match unsafe{(**self).qtype}.saturating_mul(-1){
1102 qtype::CHAR => Ok(unsafe{(**self).value.byte as char}),
1103 _ => Err("not a char\0")
1104 }
1105 }
1106
1107 #[inline]
1108 fn get_symbol(&self) -> Result<&str, &'static str>{
1109 if (unsafe{(**self).qtype} == -qtype::SYMBOL) || (unsafe{(**self).qtype} == qtype::ERROR){
1110 Ok(S_to_str(unsafe{(**self).value.symbol}))
1111 }
1112 else{
1113 Err("not a symbol\0")
1114 }
1115 }
1116
1117 #[inline]
1118 fn get_str(&self) -> Result<&str, &'static str>{
1119 match unsafe{(**self).qtype}{
1120 qtype::CHAR => {
1121 Ok(unsafe{str::from_utf8_unchecked_mut(self.as_mut_slice::<G>())})
1122 },
1123 _ => Err("not a string\0")
1124 }
1125 }
1126
1127 #[inline]
1128 fn get_string(&self) -> Result<String, &'static str>{
1129 match unsafe{(**self).qtype}{
1130 qtype::CHAR => {
1131 Ok(unsafe{String::from_utf8_unchecked(self.as_mut_slice::<G>().to_vec())})
1132 },
1133 _ => Err("not a string\0")
1134 }
1135 }
1136
1137 #[inline]
1138 fn get_dictionary(&self) -> Result<K, &'static str>{
1139 match unsafe{(**self).qtype}{
1140 qtype::TABLE => {
1141 Ok(unsafe{(**self).value.table})
1142 },
1143 _ => Err("not a table\0")
1144 }
1145 }
1146
1147 #[inline]
1148 fn get_attribute(&self) -> i8{
1149 unsafe{(**self).attribute}
1150 }
1151
1152 #[inline]
1153 fn get_refcount(&self) -> i32{
1154 unsafe{(**self).refcount}
1155 }
1156
1157 #[inline]
1158 fn append(&mut self, list: K)->Result<K, &'static str>{
1159 if unsafe{(**self).qtype} >= 0 && unsafe{(**self).qtype} == unsafe{(*list).qtype}{
1160 Ok(unsafe{native::jv(self, list)})
1161 }
1162 else{
1163 Err("not a list or types do not match\0")
1164 }
1165 }
1166
1167 #[inline]
1168 fn push(&mut self, atom: K)->Result<K, &'static str>{
1169 if unsafe{(**self).qtype} == 0 {
1170 Ok(unsafe{native::jk(self, atom)})
1171 }
1172 else{
1173 Err("not a list or types do not match\0")
1174 }
1175 }
1176
1177 #[inline]
1178 fn push_raw<T>(&mut self, mut atom: T)->Result<K, &'static str>{
1179 match unsafe{(**self).qtype}{
1180 _t@1..=19 => Ok(unsafe{native::ja(self, std::mem::transmute::<*mut T, *mut V>(&mut atom))}),
1181 _ => Err("not a simple list or types do not match\0")
1182 }
1183 }
1184
1185 #[inline]
1186 fn push_symbol(&mut self, symbol: &str)->Result<K, &'static str>{
1187 if unsafe{(**self).qtype} == qtype::SYMBOL {
1188 Ok(unsafe{native::js(self, native::ss(str_to_S!(symbol)))})
1189 }
1190 else{
1191 Err("not a symbol list\0")
1192 }
1193 }
1194
1195 #[inline]
1196 fn push_symbol_n(&mut self, symbol: &str, n: I)->Result<K, &'static str>{
1197 if unsafe{(**self).qtype} == qtype::SYMBOL {
1198 Ok(unsafe{native::js(self, native::sn(str_to_S!(symbol), n))})
1199 }
1200 else{
1201 Err("not a symbol list or types do not match\0")
1202 }
1203 }
1204
1205 #[inline]
1206 fn len(&self) -> i64{
1207 unsafe{
1208 if (**self).qtype < 0 || (**self).qtype == qtype::NULL{
1209 // Atom or (::)
1210 1
1211 }
1212 else if (**self).qtype == qtype::TABLE{
1213 // Table
1214 // Access underlying table (dictionary structure) and retrieve values of the dictionary.
1215 // The values (columns) is assured to be a list of lists as it is a table. so cast it to list of `K`.
1216 // Size of the table is a length of the first column.
1217 (*((**self).value.table).as_mut_slice::<K>()[1].as_mut_slice::<K>()[0]).value.list.n
1218 }
1219 else if (**self).qtype == qtype::DICTIONARY{
1220 // Dictionary
1221 // Access to keys of the dictionary and retrieve its length.
1222 (*(*self).as_mut_slice::<K>()[0]).value.list.n
1223 }
1224 else{
1225 // List
1226 (**self).value.list.n
1227 }
1228 }
1229 }
1230
1231 #[inline]
1232 fn get_type(&self) -> i8{
1233 unsafe{(**self).qtype}
1234 }
1235
1236 #[inline]
1237 fn set_type(&self, qtype: i8){
1238 unsafe{(**self).qtype=qtype};
1239 }
1240
1241 #[inline]
1242 fn q_ipc_encode(&self, mode: I) -> Result<K, &'static str>{
1243 let result=error_to_string(unsafe{
1244 native::b9(mode, *self)
1245 });
1246 match unsafe{(*result).qtype}{
1247 qtype::ERROR => {
1248 decrement_reference_count(result);
1249 Err("failed to encode\0")
1250 },
1251 _ => Ok(result)
1252 }
1253 }
1254
1255 #[inline]
1256 fn q_ipc_decode(&self) -> Result<K, &'static str>{
1257 match unsafe{(**self).qtype}{
1258 qtype::BYTE => {
1259 let result=error_to_string(unsafe{
1260 native::d9(*self)
1261 });
1262 match unsafe{(*result).qtype}{
1263 qtype::ERROR => {
1264 decrement_reference_count(result);
1265 Err("failed to decode\0")
1266 },
1267 _ => Ok(result)
1268 }
1269 },
1270 _ => Err("not bytes\0")
1271 }
1272 }
1273}
1274
1275impl k0{
1276 /// Derefer `k0` as a mutable slice. For supported types, see [`as_mut_slice`](trait.KUtility.html#tymethod.as_mut_slice).
1277 /// # Note
1278 /// Used if `K` needs to be sent to another thread. `K` cannot implement `Send` and therefore
1279 /// its inner struct must be sent instead.
1280 /// # Example
1281 /// See the example of [`setm`](native/fn.setm.html).
1282 #[inline]
1283 pub fn as_mut_slice<'a, T>(&mut self) -> &'a mut[T]{
1284 unsafe{
1285 std::slice::from_raw_parts_mut(self.value.list.G0.as_mut_ptr() as *mut T, self.value.list.n as usize)
1286 }
1287 }
1288}
1289
1290//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
1291// Utility //
1292//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
1293
1294//%% Utility %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
1295
1296/// Convert `S` to `&str`. This function is intended to convert symbol type (null-terminated char-array) to `str`.
1297/// # Extern
1298/// ```no_run
1299/// use kdb_c_api::*;
1300///
1301/// #[no_mangle]
1302/// pub extern "C" fn print_symbol(symbol: K) -> K{
1303/// unsafe{
1304/// if (*symbol).qtype == -qtype::SYMBOL{
1305/// println!("symbol: `{}", S_to_str((*symbol).value.symbol));
1306/// }
1307/// // return null
1308/// KNULL
1309/// }
1310/// }
1311/// ```
1312/// ```q
1313/// q)print_symbol:`libc_api_examples 2: (`print_symbol; 1)
1314/// q)a:`kx
1315/// q)print_symbol a
1316/// symbol: `kx
1317/// ```
1318#[inline]
1319pub fn S_to_str<'a>(cstring: S) -> &'a str{
1320 unsafe{
1321 CStr::from_ptr(cstring).to_str().unwrap()
1322 }
1323}
1324
1325/// Convert null-terminated `&str` to `S`.
1326/// # Example
1327/// ```no_run
1328/// use kdb_c_api::*;
1329///
1330/// #[no_mangle]
1331/// pub extern "C" fn pingpong2(_: K) -> K{
1332/// unsafe{native::k(0, null_terminated_str_to_S("ping\0"), new_int(77), KNULL)}
1333/// }
1334/// ```
1335/// ```q
1336/// q)ping:{[int] `$string[int], "_pong!!"};
1337/// q)pingpong: `libc_api_examples 2: (`pingpong2; 1);
1338/// q)pingpong[]
1339/// `77_pong!!
1340/// ```
1341#[inline]
1342pub fn null_terminated_str_to_S(string: &str) -> S {
1343 unsafe{
1344 CStr::from_bytes_with_nul_unchecked(string.as_bytes()).as_ptr() as S
1345 }
1346}
1347
1348/// Convert null terminated `&str` into `const_S`. Expected usage is to build
1349/// a q error object with `krr`.
1350/// # Example
1351/// ```no_run
1352/// use kdb_c_api::*;
1353/// use kdb_c_api::native::*;
1354///
1355/// pub extern "C" fn must_be_int2(obj: K) -> K{
1356/// unsafe{
1357/// if (*obj).qtype != -qtype::INT{
1358/// krr(null_terminated_str_to_const_S("not an int\0"))
1359/// }
1360/// else{
1361/// KNULL
1362/// }
1363/// }
1364/// }
1365/// ```
1366/// ```q
1367/// q)check:`libc_api_examples 2: (`must_be_int; 1)
1368/// q)a:100
1369/// q)check a
1370/// 'not an int
1371/// [0] check a
1372/// ^
1373/// q)a:42i
1374/// q)check a
1375/// ```
1376pub fn null_terminated_str_to_const_S(string: &str) -> const_S {
1377 string.as_bytes().as_ptr() as const_S
1378}
1379
1380//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
1381// Re-export //
1382//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
1383
1384//%% Constructor %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
1385
1386/// Constructor of q bool object. Relabeling of `kb`.
1387/// # Example
1388/// ```no_run
1389/// use kdb_c_api::*;
1390///
1391/// #[no_mangle]
1392/// pub extern "C" fn create_bool(_: K) -> K{
1393/// new_bool(0)
1394/// }
1395/// ```
1396/// ```q
1397/// q)no: `libc_api_examples 2: (`create_bool; 1);
1398/// q)no[]
1399/// 0b
1400/// ```
1401#[inline]
1402pub fn new_bool(boolean: I) -> K{
1403 unsafe{
1404 native::kb(boolean)
1405 }
1406}
1407
1408/// Constructor of q GUID object. Relabeling of `ku`.
1409/// # Example
1410/// ```no_run
1411/// use kdb_c_api::*;
1412///
1413/// #[no_mangle]
1414/// pub extern "C" fn create_guid(_: K) -> K{
1415/// new_guid([0x1e_u8, 0x11, 0x17, 0x0c, 0x42, 0x24, 0x25, 0x2c, 0x1c, 0x14, 0x1e, 0x22, 0x4d, 0x3d, 0x46, 0x24])
1416/// }
1417/// ```
1418/// ```q
1419/// q)create_guid: `libc_api_examples 2: (`create_guid; 1);
1420/// q)create_guid[]
1421/// 1e11170c-4224-252c-1c14-1e224d3d4624
1422/// ```
1423#[inline]
1424pub fn new_guid(guid: [G; 16]) -> K{
1425 unsafe{
1426 native::ku(U::new(guid))
1427 }
1428}
1429
1430/// Constructor of q byte object. Relabeling of `kg`.
1431/// # Example
1432/// ```no_run
1433/// use kdb_c_api::*;
1434///
1435/// #[no_mangle]
1436/// pub extern "C" fn create_byte(_: K) -> K{
1437/// new_byte(0x3c)
1438/// }
1439/// ```
1440/// ```q
1441/// q)create_byte: `libc_api_examples 2: (`create_byte; 1);
1442/// q)create_byte[]
1443/// 0x3c
1444/// ```
1445#[inline]
1446pub fn new_byte(byte: I) -> K{
1447 unsafe{
1448 native::kg(byte)
1449 }
1450}
1451
1452/// Constructor of q short object. Relabeling of `kh`.
1453/// # Example
1454/// ```no_run
1455/// use kdb_c_api::*;
1456///
1457/// #[no_mangle]
1458/// pub extern "C" fn create_short(_: K) -> K{
1459/// new_short(-144)
1460/// }
1461/// ```
1462/// ```q
1463/// q)shortage: `libc_api_examples 2: (`create_short; 1);
1464/// q)shortage[]
1465/// -144h
1466/// ```
1467#[inline]
1468pub fn new_short(short: I) -> K{
1469 unsafe{
1470 native::kh(short)
1471 }
1472}
1473
1474/// Constructor of q int object. Relabeling of `ki`.
1475/// # Example
1476/// ```no_run
1477/// use kdb_c_api::*;
1478///
1479/// #[no_mangle]
1480/// pub extern "C" fn create_int(_: K) -> K{
1481/// new_int(86400000)
1482/// }
1483/// ```
1484/// ```q
1485/// q)trvial: `libc_api_examples 2: (`create_int; 1);
1486/// q)trivial[]
1487/// 86400000i
1488/// ```
1489#[inline]
1490pub fn new_int(int: I) -> K{
1491 unsafe{
1492 native::ki(int)
1493 }
1494}
1495
1496/// Constructor of q long object. Relabeling of `kj`.
1497/// # Example
1498/// ```no_run
1499/// use kdb_c_api::*;
1500///
1501/// #[no_mangle]
1502/// pub extern "C" fn create_long(_: K) -> K{
1503/// new_long(-668541276001729000)
1504/// }
1505/// ```
1506/// ```q
1507/// q)lengthy: `libc_api_examples 2: (`create_long; 1);
1508/// q)lengthy[]
1509/// -668541276001729000
1510/// ```
1511#[inline]
1512pub fn new_long(long: J) -> K{
1513 unsafe{
1514 native::kj(long)
1515 }
1516}
1517
1518/// Constructor of q real object. Relabeling of `ke`.
1519/// # Example
1520/// ```no_run
1521/// use kdb_c_api::*;
1522///
1523/// #[no_mangle]
1524/// pub extern "C" fn create_real(_: K) -> K{
1525/// new_real(0.00324)
1526/// }
1527/// ```
1528/// ```q
1529/// q)reality: `libc_api_examples 2: (`create_real; 1);
1530/// q)reality[]
1531/// 0.00324e
1532/// ```
1533#[inline]
1534pub fn new_real(real: F) -> K{
1535 unsafe{
1536 native::ke(real)
1537 }
1538}
1539
1540/// Constructor of q float object. Relabeling of `kf`.
1541/// # Example
1542/// ```
1543/// use kdb_c_api::*;
1544///
1545/// #[no_mangle]
1546/// pub extern "C" fn create_float(_: K) -> K{
1547/// new_float(-6302.620)
1548/// }
1549/// ```
1550/// ```q
1551/// q)coffee_float: `libc_api_examples 2: (`create_float; 1);
1552/// q)coffee_float[]
1553/// -6302.62
1554/// ```
1555#[inline]
1556pub fn new_float(float: F) -> K{
1557 unsafe{
1558 native::kf(float)
1559 }
1560}
1561
1562/// Constructor of q char object. Relabeling of `kc`.
1563/// # Example
1564/// ```no_run
1565/// use kdb_c_api::*;
1566///
1567/// #[no_mangle]
1568/// pub extern "C" fn create_char2(_: K) -> K{
1569/// new_char('t')
1570/// }
1571/// ```
1572/// ```q
1573/// q)heavy: `libc_api_examples 2: (`create_char2; 1);
1574/// q)heavy[]
1575/// "t"
1576/// ```
1577#[inline]
1578pub fn new_char(character: char) -> K{
1579 unsafe{
1580 native::kc(character as I)
1581 }
1582}
1583
1584/// Constructor of q symbol object. Relabeling of `ks`.
1585/// # Example
1586/// ```no_run
1587/// use kdb_c_api::*;
1588///
1589/// #[no_mangle]
1590/// pub extern "C" fn create_symbol2(_: K) -> K{
1591/// new_symbol("symbolic")
1592/// }
1593/// ```
1594/// ```q
1595/// q)hard: `libc_api_examples 2: (`create_symbol2; 1);
1596/// q)hard[]
1597/// `symbolic
1598/// q)`symbolic ~ hard[]
1599/// 1b
1600/// ```
1601#[inline]
1602pub fn new_symbol(symbol: &str) -> K{
1603 unsafe{
1604 native::ks(str_to_S!(symbol))
1605 }
1606}
1607
1608/// Constructor of q timestamp from elapsed time in nanoseconds since kdb+ epoch (`2000.01.01`). Relabeling of `ktj`.
1609/// ```no_run
1610/// use kdb_c_api::*;
1611///
1612/// #[no_mangle]
1613/// pub extern "C" fn create_timestamp2(_: K) -> K{
1614/// // 2015.03.16D00:00:00:00.000000000
1615/// new_timestamp(479779200000000000)
1616/// }
1617/// ```
1618/// ```q
1619/// q)stamp: `libc_api_examples 2: (`create_timestamp2; 1);
1620/// q)stamp[]
1621/// 2015.03.16D00:00:00.000000000
1622/// ```
1623#[inline]
1624pub fn new_timestamp(nanoseconds: J) -> K{
1625 unsafe{
1626 native::ktj(-qtype::TIMESTAMP as I, nanoseconds)
1627 }
1628}
1629
1630/// Create a month object from the number of months since kdb+ epoch (`2000.01.01`).
1631/// This is a complememtal constructor of missing month type.
1632/// # Example
1633/// ```no_run
1634/// use kdb_c_api::*;
1635///
1636/// #[no_mangle]
1637/// pub extern "C" fn create_month(_: K) -> K{
1638/// // 2010.07m
1639/// new_month(126)
1640/// }
1641/// ```
1642/// ```q
1643/// q)create_month: `libc_api_examples 2: (`create_month; 1);
1644/// q)create_month[]
1645/// 2010.07m
1646/// ```
1647#[inline]
1648pub fn new_month(months: I) -> K{
1649 unsafe{
1650 let month=native::ka(-qtype::MONTH as I);
1651 (*month).value.int=months;
1652 month
1653 }
1654}
1655
1656/// Constructor of q date object. Relabeling of `kd`.
1657/// # Example
1658/// ```no_run
1659/// use kdb_c_api::*;
1660///
1661/// #[no_mangle]
1662/// pub extern "C" fn create_date(_: K) -> K{
1663/// // 1999.12.25
1664/// new_date(-7)
1665/// }
1666/// ```
1667/// ```q
1668/// q)nostradamus: `libc_api_examples 2: (`create_date; 1);
1669/// q)nostradamus[]
1670/// 1999.12.25
1671/// ```
1672#[inline]
1673pub fn new_date(days: I) -> K{
1674 unsafe{
1675 native::kd(days)
1676 }
1677}
1678
1679/// Constructor of q datetime object from the number of days since kdb+ epoch (`2000.01.01`). Relabeling of `kz`.
1680/// ```no_run
1681/// use kdb_c_api::*;
1682///
1683/// #[no_mangle]
1684/// pub extern "C" fn create_datetime(_: K) -> K{
1685/// // 2015.03.16T12:00:00:00.000
1686/// new_datetime(5553.5)
1687/// }
1688/// ```
1689/// ```q
1690/// q)omega_date: libc_api_examples 2: (`create_datetime; 1);
1691/// q)omega_date[]
1692/// 2015.03.16T12:00:00.000
1693/// ```
1694#[inline]
1695pub fn new_datetime(days: F) -> K{
1696 unsafe{
1697 native::kz(days)
1698 }
1699}
1700
1701/// Constructor of q timespan object from nanoseconds. Relabeling of `ktj`.
1702/// ```no_run
1703/// use kdb_c_api::*;
1704///
1705/// #[no_mangle]
1706/// pub extern "C" fn create_timespan2(_: K) -> K{
1707/// // -1D01:30:00.001234567
1708/// new_timespan(-91800001234567)
1709/// }
1710/// ```
1711/// ```q
1712/// q)duration: libc_api_examples 2: (`create_timespan2; 1);
1713/// q)duration[]
1714/// -1D01:30:00.001234567
1715/// ```
1716#[inline]
1717pub fn new_timespan(nanoseconds: J) -> K{
1718 unsafe{
1719 native::ktj(-qtype::TIMESPAN as I, nanoseconds)
1720 }
1721}
1722
1723/// Create a month object. This is a complememtal constructor of
1724/// missing minute type.
1725/// # Example
1726/// ```no_run
1727/// use kdb_c_api::*;
1728///
1729/// #[no_mangle]
1730/// pub extern "C" fn create_minute(_: K) -> K{
1731/// // 10:40
1732/// new_minute(640)
1733/// }
1734/// ```
1735/// ```q
1736/// q)minty: `libc_api_examples 2: (`create_minute; 1);
1737/// q)minty[]
1738/// 10:40
1739/// ```
1740#[inline]
1741pub fn new_minute(minutes: I) -> K{
1742 unsafe{
1743 let minute=native::ka(-qtype::MINUTE as I);
1744 (*minute).value.int=minutes;
1745 minute
1746 }
1747}
1748
1749/// Create a month object. This is a complememtal constructor of
1750/// missing second type.
1751/// # Example
1752/// ```no_run
1753/// use kdb_c_api::*;
1754///
1755/// #[no_mangle]
1756/// pub extern "C" fn create_second(_: K) -> K{
1757/// // -02:00:00
1758/// new_second(-7200)
1759/// }
1760/// ```
1761/// ```q
1762/// q)third: `libc_api_examples 2: (`create_second; 1);
1763/// q)third[]
1764/// -02:00:00
1765/// ```
1766#[inline]
1767pub fn new_second(seconds: I) -> K{
1768 unsafe{
1769 let second=native::ka(-qtype::SECOND as I);
1770 (*second).value.int=seconds;
1771 second
1772 }
1773}
1774
1775/// Constructor of q time object. Relabeling of `kt`.
1776/// # Example
1777/// ```no_run
1778/// use kdb_c_api::*;
1779///
1780/// #[no_mangle]
1781/// pub extern "C" fn create_time(_: K) -> K{
1782/// // -01:30:00.123
1783/// new_time(-5400123)
1784/// }
1785/// ```
1786/// ```q
1787/// q)ancient: libc_api_examples 2: (`create_time; 1);
1788/// q)ancient[]
1789/// -01:30:00.123
1790/// ```
1791#[inline]
1792pub fn new_time(milliseconds: I) -> K{
1793 unsafe{
1794 native::kt(milliseconds)
1795 }
1796}
1797
1798/// Constructor of q simple list.
1799/// # Example
1800/// See the example of [`new_dictionary`](fn.new_dictionary.html).
1801#[inline]
1802pub fn new_simple_list(qtype: i8, length: J) -> K{
1803 unsafe{
1804 native::ktn(qtype as I, length)
1805 }
1806}
1807
1808/// Constructor of q string object.
1809/// # Example
1810/// ```no_run
1811/// use kdb_c_api::*;
1812///
1813/// #[no_mangle]
1814/// pub extern "C" fn create_string(_: K) -> K{
1815/// new_string("this is a text.")
1816/// }
1817/// ```
1818/// ```q
1819/// q)text: libc_api_examples 2: (`create_string; 1);
1820/// q)text[]
1821/// "this is a text."
1822/// ```
1823#[inline]
1824pub fn new_string(string: &str) -> K{
1825 unsafe{
1826 native::kp(str_to_S!(string))
1827 }
1828}
1829
1830/// Constructor if q string object with a fixed length.
1831/// # Example
1832/// ```no_run
1833/// use kdb_c_api::*;
1834///
1835/// #[no_mangle]
1836/// pub extern "C" fn create_string2(_: K) -> K{
1837/// new_string_n("The meeting was too long and I felt it s...", 24)
1838/// }
1839/// ```
1840/// ```q
1841/// q)speak_inwardly: libc_api_examples 2: (`create_string2; 1);
1842/// q)speak_inwardly[]
1843/// "The meeting was too long"
1844/// ```
1845#[inline]
1846pub fn new_string_n(string: &str, length: J) -> K{
1847 unsafe{
1848 native::kpn(str_to_S!(string), length)
1849 }
1850}
1851
1852/// Constructor of q dictionary object.
1853/// # Example
1854/// ```no_run
1855/// use kdb_c_api::*;
1856///
1857/// #[no_mangle]
1858/// pub extern "C" fn create_dictionary() -> K{
1859/// let keys=new_simple_list(qtype::INT, 2);
1860/// keys.as_mut_slice::<I>()[0..2].copy_from_slice(&[0, 1]);
1861/// let values=new_simple_list(qtype::COMPOUND, 2);
1862/// let date_list=new_simple_list(qtype::DATE, 3);
1863/// // 2000.01.01 2000.01.02 2000.01.03
1864/// date_list.as_mut_slice::<I>()[0..3].copy_from_slice(&[0, 1, 2]);
1865/// let string=new_string("I'm afraid I would crash the application...");
1866/// values.as_mut_slice::<K>()[0..2].copy_from_slice(&[date_list, string]);
1867/// new_dictionary(keys, values)
1868/// }
1869/// ```
1870/// ```q
1871/// q)create_dictionary: `libc_api_examples 2: (`create_dictionary; 1);
1872/// q)create_dictionary[]
1873/// 0| 2000.01.01 2000.01.02 2000.01.03
1874/// 1| "I'm afraid I would crash the application..."
1875/// ```
1876#[inline]
1877pub fn new_dictionary(keys: K, values: K) -> K{
1878 unsafe{
1879 native::xD(keys, values)
1880 }
1881}
1882
1883/// Constructor of q error. The input must be null-terminated.
1884/// # Example
1885/// ```no_run
1886/// use kdb_c_api::*;
1887///
1888/// pub extern "C" fn thai_kick(_: K) -> K{
1889/// new_error("Thai kick unconditionally!!\0")
1890/// }
1891/// ```
1892/// ```q
1893/// q)monstrous: `libc_api_examples 2: (`thai_kick; 1);
1894/// q)monstrous[]
1895/// 'Thai kick unconditionally!!
1896/// [0] monstrous[]
1897/// ^
1898/// ```
1899#[inline]
1900pub fn new_error(message: &str) -> K{
1901 unsafe{
1902 native::krr(null_terminated_str_to_const_S(message))
1903 }
1904}
1905
1906/// Similar to `new_error` but this function appends a system-error message to string `S` before passing it to internal `krr`.
1907/// The input must be null-terminated.
1908#[inline]
1909pub fn new_error_os(message: &str) -> K{
1910 unsafe{
1911 native::orr(null_terminated_str_to_const_S(message))
1912 }
1913}
1914
1915/// Convert an error object into usual K object which has the error string in the field `s`.
1916/// # Example
1917/// ```no_run
1918/// use kdb_c_api::*;
1919///
1920/// extern "C" fn no_panick(func: K, args: K) -> K{
1921/// let result=error_to_string(apply(func, args));
1922/// if result.get_type() == qtype::ERROR{
1923/// println!("FYI: {}", result.get_symbol().unwrap());
1924/// // Decrement reference count of the error object which is no longer used.
1925/// decrement_reference_count(result);
1926/// KNULL
1927/// }
1928/// else{
1929/// result
1930/// }
1931/// }
1932/// ```
1933/// ```q
1934/// q)chill: `libc_api_examples 2: (`no_panick; 2);
1935/// q)chill[$; ("J"; "42")]
1936/// success!
1937/// 42
1938/// q)chill[+; (1; `a)]
1939/// FYI: type
1940/// ```
1941#[inline]
1942pub fn error_to_string(error: K) -> K{
1943 unsafe{
1944 native::ee(error)
1945 }
1946}
1947
1948//%% Symbol %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
1949
1950/// Intern `n` chars from a char array.
1951/// Returns an interned char array and should be used to add char array to a symbol vector.
1952/// # Example
1953/// See the example of [`flip`](fn.flip.html).
1954#[inline]
1955pub fn internalize_n(string: S, n: I) -> S{
1956 unsafe{
1957 native::sn(string, n)
1958 }
1959}
1960
1961/// Intern a null-terminated char array.
1962/// Returns an interned char array and should be used to add char array to a symbol vector.
1963/// # Example
1964/// See the example of [`flip`](fn.flip.html).
1965#[inline]
1966pub fn internalize(string: S) -> S{
1967 unsafe{
1968 native::ss(string)
1969 }
1970}
1971
1972//%% Table %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
1973
1974/// Constructor of q table object from a q dictionary object.
1975/// # Note
1976/// Basically this is a `flip` command of q. Hence the value of the dictionary must have
1977/// lists as its elements.
1978/// ```no_run
1979/// use kdb_c_api::*;
1980///
1981/// #[no_mangle]
1982/// pub extern "C" fn create_table2(_: K) -> K{
1983/// // Build keys
1984/// let keys=new_simple_list(qtype::SYMBOL, 2);
1985/// let keys_slice=keys.as_mut_slice::<S>();
1986/// keys_slice[0]=internalize(str_to_S!("time"));
1987/// keys_slice[1]=internalize_n(str_to_S!("temperature_and_humidity"), 11);
1988///
1989/// // Build values
1990/// let values=new_simple_list(qtype::COMPOUND, 2);
1991/// let time=new_simple_list(qtype::TIMESTAMP, 3);
1992/// // 2003.10.10D02:24:19.167018272 2006.05.24D06:16:49.419710368 2008.08.12D23:12:24.018691392
1993/// time.as_mut_slice::<J>().copy_from_slice(&[119067859167018272_i64, 201766609419710368, 271897944018691392]);
1994/// let temperature=new_simple_list(qtype::FLOAT, 3);
1995/// temperature.as_mut_slice::<F>().copy_from_slice(&[22.1_f64, 24.7, 30.5]);
1996/// values.as_mut_slice::<K>().copy_from_slice(&[time, temperature]);
1997///
1998/// flip(new_dictionary(keys, values))
1999/// }
2000/// ```
2001/// ```q
2002/// q)climate_change: libc_api_examples 2: (`create_table2; 1);
2003/// q)climate_change[]
2004/// time temperature
2005/// -----------------------------------------
2006/// 2003.10.10D02:24:19.167018272 22.1
2007/// 2006.05.24D06:16:49.419710368 24.7
2008/// 2008.08.12D23:12:24.018691392 30.5
2009/// ```
2010#[inline]
2011pub fn flip(dictionary: K) -> K{
2012 match unsafe{(*dictionary).qtype}{
2013 qtype::DICTIONARY => unsafe{native::xT(dictionary)},
2014 _ => unsafe{native::krr(null_terminated_str_to_const_S("not a dictionary\0"))}
2015 }
2016}
2017
2018/// Constructor of simple q table object from a q keyed table object.
2019/// # Example
2020/// ```no_run
2021/// use kdb_c_api::*;
2022///
2023/// #[no_mangle]
2024/// pub extern "C" fn create_table2(_: K) -> K{
2025/// // Build keys
2026/// let keys=new_simple_list(qtype::SYMBOL, 2);
2027/// let keys_slice=keys.as_mut_slice::<S>();
2028/// keys_slice[0]=internalize(str_to_S!("time"));
2029/// keys_slice[1]=internalize_n(str_to_S!("temperature_and_humidity"), 11);
2030///
2031/// // Build values
2032/// let values=new_simple_list(qtype::COMPOUND, 2);
2033/// let time=new_simple_list(qtype::TIMESTAMP, 3);
2034/// // 2003.10.10D02:24:19.167018272 2006.05.24D06:16:49.419710368 2008.08.12D23:12:24.018691392
2035/// time.as_mut_slice::<J>().copy_from_slice(&[119067859167018272_i64, 201766609419710368, 271897944018691392]);
2036/// let temperature=new_simple_list(qtype::FLOAT, 3);
2037/// temperature.as_mut_slice::<F>().copy_from_slice(&[22.1_f64, 24.7, 30.5]);
2038/// values.as_mut_slice::<K>().copy_from_slice(&[time, temperature]);
2039///
2040/// flip(new_dictionary(keys, values))
2041/// }
2042///
2043/// #[no_mangle]
2044/// pub extern "C" fn create_keyed_table(dummy: K) -> K{
2045/// enkey(create_table2(dummy), 1)
2046/// }
2047///
2048/// #[no_mangle]
2049/// pub extern "C" fn keyed_to_simple_table(dummy: K) -> K{
2050/// unkey(create_keyed_table(dummy))
2051/// }
2052/// ```
2053/// ```q
2054/// q)unkey: libc_api_examples 2: (`keyed_to_simple_table; 1);
2055/// q)unkey[]
2056/// time temperature
2057/// -----------------------------------------
2058/// 2003.10.10D02:24:19.167018272 22.1
2059/// 2006.05.24D06:16:49.419710368 24.7
2060/// 2008.08.12D23:12:24.018691392 30.5
2061/// ```
2062#[inline]
2063pub fn unkey(keyed_table: K) -> K{
2064 match unsafe{(*keyed_table).qtype}{
2065 qtype::DICTIONARY => unsafe{native::ktd(keyed_table)},
2066 _ => unsafe{native::krr(null_terminated_str_to_const_S("not a keyed table\0"))}
2067 }
2068}
2069
2070/// Constructor of q keyed table object.
2071/// # Parameters
2072/// - `table`: q table object to be enkeyed.
2073/// - `n`: The number of key columns from the left.
2074/// # Example
2075/// ```no_run
2076/// use kdb_c_api::*;
2077///
2078/// #[no_mangle]
2079/// pub extern "C" fn create_table2(_: K) -> K{
2080/// // Build keys
2081/// let keys=new_simple_list(qtype::SYMBOL, 2);
2082/// let keys_slice=keys.as_mut_slice::<S>();
2083/// keys_slice[0]=internalize(str_to_S!("time"));
2084/// keys_slice[1]=internalize_n(str_to_S!("temperature_and_humidity"), 11);
2085///
2086/// // Build values
2087/// let values=new_simple_list(qtype::COMPOUND, 2);
2088/// let time=new_simple_list(qtype::TIMESTAMP, 3);
2089/// // 2003.10.10D02:24:19.167018272 2006.05.24D06:16:49.419710368 2008.08.12D23:12:24.018691392
2090/// time.as_mut_slice::<J>().copy_from_slice(&[119067859167018272_i64, 201766609419710368, 271897944018691392]);
2091/// let temperature=new_simple_list(qtype::FLOAT, 3);
2092/// temperature.as_mut_slice::<F>().copy_from_slice(&[22.1_f64, 24.7, 30.5]);
2093/// values.as_mut_slice::<K>().copy_from_slice(&[time, temperature]);
2094///
2095/// flip(new_dictionary(keys, values))
2096/// }
2097///
2098/// #[no_mangle]
2099/// pub extern "C" fn create_keyed_table(dummy: K) -> K{
2100/// enkey(create_table2(dummy), 1)
2101/// }
2102/// ```
2103/// ```q
2104/// q)locker: libc_api_examples 2: (`create_keyed_table; 1);
2105/// q)locker[]
2106/// time | temperature
2107/// -----------------------------| -----------
2108/// 2003.10.10D02:24:19.167018272| 22.1
2109/// 2006.05.24D06:16:49.419710368| 24.7
2110/// 2008.08.12D23:12:24.018691392| 30.5
2111/// ```
2112#[inline]
2113pub fn enkey(table: K, n: J) -> K{
2114 match unsafe{(*table).qtype}{
2115 qtype::TABLE => unsafe{native::knt(n, table)},
2116 _ => unsafe{native::krr(null_terminated_str_to_const_S("not a table\0"))}
2117 }
2118}
2119
2120//%% Reference Count %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
2121
2122/// Decrement reference count of the q object. The decrement must be done when `k` function gets an error
2123/// object whose type is `qtype::ERROR` and when you created an object but do not intend to return it to
2124/// q side. See details on [the reference page](https://code.kx.com/q/interfaces/c-client-for-q/#managing-memory-and-reference-counting).
2125/// # Example
2126/// ```no_run
2127/// use kdb_c_api::*;
2128///
2129/// #[no_mangle]
2130/// pub extern "C" fn agriculture(_: K)->K{
2131/// // Produce an apple.
2132/// let fruit=new_symbol("apple");
2133/// // Sow the apple seed.
2134/// decrement_reference_count(fruit);
2135/// // Return null.
2136/// KNULL
2137/// }
2138/// ```
2139/// ```q
2140/// q)do_something: libc_api_examples 2: (`agriculture; 1);
2141/// q)do_something[]
2142/// q)
2143/// ```
2144#[inline]
2145pub fn decrement_reference_count(qobject: K) -> V{
2146 unsafe{native::r0(qobject)}
2147}
2148
2149/// Increment reference count of the q object. Increment must be done when you passed arguments
2150/// to Rust function and intends to return it to q side or when you pass some `K` objects to `k`
2151/// function and intend to use the argument after the call.
2152/// See details on [the reference page](https://code.kx.com/q/interfaces/c-client-for-q/#managing-memory-and-reference-counting).
2153/// # Example
2154/// ```no_run
2155/// use kdb_c_api::*;
2156///
2157/// fn eat(apple: K){
2158/// println!("おいしい!");
2159/// }
2160///
2161/// #[no_mangle]
2162/// pub extern "C" fn satisfy_5000_men(apple: K) -> K{
2163/// for _ in 0..10{
2164/// eat(apple);
2165/// }
2166/// unsafe{native::k(0, str_to_S!("eat"), increment_reference_count(apple), KNULL);}
2167/// increment_reference_count(apple)
2168/// }
2169/// ```
2170/// ```q
2171/// q)eat:{[apple] show "Collect the clutter of apples!";}
2172/// q)bread_is_a_sermon: libc_api_examples 2: (`satisfy_5000_men; 1);
2173/// q)bread_is_a_sermon[`green_apple]
2174/// おいしい!
2175/// おいしい!
2176/// おいしい!
2177/// おいしい!
2178/// おいしい!
2179/// おいしい!
2180/// おいしい!
2181/// おいしい!
2182/// おいしい!
2183/// おいしい!
2184/// "Collect the clutter of apples!"
2185/// ```
2186#[inline]
2187pub fn increment_reference_count(qobject: K) -> K{
2188 unsafe{native::r1(qobject)}
2189}
2190
2191//%% Callback %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
2192
2193/// Remove callback from the associated kdb+ socket and call `kclose`.
2194/// Return null if the socket is invalid or not the one which had been registered by `sd1`.
2195/// # Note
2196/// A function which calls this function must be executed at the exit of the process.
2197#[inline]
2198pub fn destroy_socket(socket: I){
2199 unsafe{
2200 native::sd0(socket);
2201 }
2202}
2203
2204/// Remove callback from the associated kdb+ socket and call `kclose` if the given condition is satisfied.
2205/// Return null if the socket is invalid or not the one which had been registered by `sd1`.
2206/// # Note
2207/// A function which calls this function must be executed at the exit of the process.
2208#[inline]
2209pub fn destroy_socket_if(socket: I, condition: bool){
2210 unsafe{
2211 native::sd0x(socket, condition as I);
2212 }
2213}
2214
2215/// Register callback to the associated kdb+ socket.
2216/// ```no_run
2217/// use kdb_c_api::*;
2218///
2219/// static mut PIPE:[I; 2]=[-1, -1];
2220///
2221/// // Callback for some message queue.
2222/// extern "C" fn callback(socket: I)->K{
2223/// let mut buffer: [K; 1]=[0 as K];
2224/// unsafe{libc::read(socket, buffer.as_mut_ptr() as *mut V, 8)};
2225/// // Call `shout` function on q side with the received data.
2226/// let result=error_to_string(unsafe{native::k(0, str_to_S!("shout"), buffer[0], KNULL)});
2227/// if result.get_type() == qtype::ERROR{
2228/// eprintln!("Execution error: {}", result.get_symbol().unwrap());
2229/// decrement_reference_count(result);
2230/// };
2231/// KNULL
2232/// }
2233///
2234/// #[no_mangle]
2235/// pub extern "C" fn plumber(_: K) -> K{
2236/// if 0 != unsafe{libc::pipe(PIPE.as_mut_ptr())}{
2237/// return new_error("Failed to create pipe\0");
2238/// }
2239/// if KNULL == register_callback(unsafe{PIPE[0]}, callback){
2240/// return new_error("Failed to register callback\0");
2241/// }
2242/// // Lock symbol in a worker thread.
2243/// pin_symbol();
2244/// let handle=std::thread::spawn(move ||{
2245/// let mut precious=new_simple_list(qtype::SYMBOL, 3);
2246/// let precious_array=precious.as_mut_slice::<S>();
2247/// precious_array[0]=internalize(null_terminated_str_to_S("belief\0"));
2248/// precious_array[1]=internalize(null_terminated_str_to_S("love\0"));
2249/// precious_array[2]=internalize(null_terminated_str_to_S("hope\0"));
2250/// unsafe{libc::write(PIPE[1], std::mem::transmute::<*mut K, *mut V>(&mut precious), 8)};
2251/// });
2252/// handle.join().unwrap();
2253/// unpin_symbol();
2254/// KNULL
2255/// }
2256/// ```
2257/// ```q
2258/// q)shout:{[precious] -1 "What are the three largest elements?: ", .Q.s1 precious;};
2259/// q)fall_into_pipe: `libc_api_example 2: (`plumber; 1);
2260/// q)fall_into_pipe[]
2261/// What are the three largest elements?: `belief`love`hope
2262/// ```
2263#[inline]
2264pub fn register_callback(socket: I, function: extern fn(I) -> K) -> K{
2265 unsafe{
2266 native::sd1(socket, function)
2267 }
2268}
2269
2270//%% Miscellaneous %%//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv/
2271
2272/// Apply a function to q list object `.[func; args]`.
2273/// # Example
2274/// See the example of [`error_to_string`](fn.error_to_string.html).
2275#[inline]
2276pub fn apply(func: K, args: K) -> K{
2277 unsafe{native::dot(func, args)}
2278}
2279
2280/// Lock a location of internalized symbol in remote threads.
2281/// Returns the previously set value.
2282/// # Example
2283/// See the example of [`register_callback`](fn.register_callback.html).
2284#[inline]
2285pub fn pin_symbol() -> I{
2286 unsafe{
2287 native::setm(1)
2288 }
2289}
2290
2291/// Unlock a location of internalized symbol in remote threads.
2292/// # Example
2293/// See the example of [`register_callback`](fn.register_callback.html).
2294#[inline]
2295pub fn unpin_symbol() -> I{
2296 unsafe{
2297 native::setm(0)
2298 }
2299}
2300
2301/// Drop Rust object inside q. Passed as the first element of a foreign object.
2302/// # Parameters
2303/// - `obj`: List of (function to free the object; foreign object).
2304/// # Example
2305/// See the example of [`load_as_q_function`](fn.load_as_q_function.html).
2306pub extern "C" fn drop_q_object(obj: K) -> K{
2307 let obj_slice=obj.as_mut_slice::<K>();
2308 // Take ownership of `K` object from a raw pointer and drop at the end of this scope.
2309 unsafe{Box::from_raw(obj_slice[1])};
2310 // Fill the list with null.
2311 obj_slice.copy_from_slice(&[KNULL, KNULL]);
2312 obj
2313}
2314
2315/// Load C function as a q function (`K` object).
2316/// # Parameters
2317/// - `func`: A function takes a C function that would take `n` `K` objects as arguments and returns a `K` object.
2318/// - `n`: The number of arguments for the function.
2319/// # Example
2320/// ```no_run
2321/// use kdb_c_api::*;
2322///
2323/// #[derive(Clone, Debug)]
2324/// struct Planet{
2325/// name: String,
2326/// population: i64,
2327/// water: bool
2328/// }
2329///
2330/// impl Planet{
2331/// /// Constructor of `Planet`.
2332/// fn new(name: &str, population: i64, water: bool) -> Self{
2333/// Planet{
2334/// name: name.to_string(),
2335/// population: population,
2336/// water: water
2337/// }
2338/// }
2339///
2340/// /// Description of the planet.
2341/// fn description(&self)->String{
2342/// let mut desc=format!("The planet {} is a beautiful planet where {} people reside.", self.name, self.population);
2343/// if self.water{
2344/// desc+=" Furthermore water is flowing on the surface of it.";
2345/// }
2346/// desc
2347/// }
2348/// }
2349///
2350/// /// Example of `set_type`.
2351/// #[no_mangle]
2352/// pub extern "C" fn eden(_: K) -> K{
2353/// let earth=Planet::new("earth", 7500_000_000, true);
2354/// let foreign=new_simple_list(qtype::COMPOUND, 2);
2355/// let foreign_slice=foreign.as_mut_slice::<K>();
2356/// foreign_slice[0]=drop_q_object as K;
2357/// foreign_slice[1]=Box::into_raw(Box::new(earth)) as K;
2358/// // Set as foreign object.
2359/// foreign.set_type(qtype::FOREIGN);
2360/// foreign
2361/// }
2362///
2363/// extern "C" fn invade(planet: K, action: K) -> K{
2364/// let obj=planet.as_mut_slice::<K>()[1] as *const Planet;
2365/// println!("{:?}", unsafe{obj.as_ref()}.unwrap());
2366/// let mut desc=unsafe{obj.as_ref()}.unwrap().description();
2367/// if action.get_bool().unwrap(){
2368/// desc+=" You shall not curse what God blessed.";
2369/// }
2370/// else{
2371/// desc+=" I perceived I could find favor of God by blessing them.";
2372/// }
2373/// new_string(&desc)
2374/// }
2375///
2376/// /// Example of `load_as_q_function`.
2377/// #[no_mangle]
2378/// pub extern "C" fn probe(planet: K)->K{
2379/// // Return monadic function
2380/// unsafe{native::k(0, str_to_S!("{[func; planet] func[planet]}"), load_as_q_function(invade as *const V, 2), planet, KNULL)}
2381/// }
2382/// ```
2383/// ```q
2384/// q)eden: libc_api_example 2: (`eden; 1);
2385/// q)earth: eden[]
2386/// q)type earth
2387/// 112h
2388/// q)probe: libc_api_example 2: (`probe; 1);
2389/// q)invade: probe[earth];
2390/// q)\c 25 200
2391/// q)invade 1b
2392/// "The planet earth is a beautiful planet where 7500000000 people reside. Furthermore water is flowing on the surface of it. You shall not curse what God blessed."
2393/// ```
2394#[inline]
2395pub fn load_as_q_function(func: *const V, n: J) -> K{
2396 unsafe{
2397 native::dl(func, n)
2398 }
2399}
2400
2401/// Convert ymd to the number of days from `2000.01.01`.
2402/// # Example
2403/// ```no_run
2404/// use kdb_c_api::*;
2405///
2406/// fn main(){
2407///
2408/// let days=ymd_to_days(2020, 4, 1);
2409/// assert_eq!(days, 7396);
2410///
2411/// }
2412/// ```
2413#[inline]
2414pub fn ymd_to_days(year: I, month: I, date:I) -> I{
2415 unsafe{
2416 native::ymd(year, month, date)
2417 }
2418}
2419
2420/// Convert the number of days from `2000.01.01` to a number expressed as `yyyymmdd`.
2421/// # Example
2422/// ```no_run
2423/// use kdb_c_api::*;
2424///
2425/// fn main(){
2426///
2427/// let number=days_to_ymd(7396);
2428/// assert_eq!(number, 20200401);
2429///
2430/// }
2431/// ```
2432#[inline]
2433pub fn days_to_ymd(days: I) -> I{
2434 unsafe{
2435 native::dj(days)
2436 }
2437}