Corto API Reference
  1. subject  In-memory Store

    Access and populate the in-memory store.

  2. chevron_right  corto_create
  3. •  Signature
  4. •  See also
  5. chevron_right  corto_declare
  6. •  Signature
  7. •  See also
  8. chevron_right  corto_define
  9. •  Signature
  10. •  See also
  11. chevron_right  corto_delete
  12. •  Signature
  13. •  See also
  14. chevron_right  corto_update
  15. •  Signature
  16. •  See also
  17. chevron_right  corto_update_begin
  18. •  Signature
  19. •  See also
  20. chevron_right  corto_update_end
  21. •  Signature
  22. •  See also
  23. chevron_right  corto_update_cancel
  24. •  Signature
  25. •  See also
  26. chevron_right  corto_invalidate
  27. •  Signature
  28. •  See also
  29. chevron_right  corto_claim
  30. •  Signature
  31. •  See also
  32. chevron_right  corto_release
  33. •  Signature
  34. •  See also
  35. chevron_right  corto_lookup
  36. •  Signature
  37. •  See also
  38. chevron_right  corto_resolve
  39. •  Signature
  40. •  See also
  41. chevron_right  corto_observe
  42. •  Signature
  43. chevron_right  corto_observe fluent methods
  44. •  disabled
  45. •  dispatcher
  46. •  instance
  47. •  type
  48. •  callback
  49. •  See also
  50. chevron_right  corto_unobserve
  51. •  Signature
  52. •  See also
  53. chevron_right  corto_read_begin
  54. •  Signature
  55. •  See also
  56. chevron_right  corto_read_end
  57. •  Signature
  58. •  See also
  59. chevron_right  corto_lock
  60. •  Signature
  61. •  See also
  62. chevron_right  corto_unlock
  63. •  Signature
  64. •  See also
  65. chevron_right  corto_set_attr
  66. •  Signature
  67. •  See also
  68. chevron_right  corto_get_attr
  69. •  Signature
  70. •  See also
  71. chevron_right  corto_set_source
  72. •  Signature
  73. •  See also
  74. chevron_right  corto_get_source
  75. •  Signature
  76. •  See also
  77. chevron_right  corto_copy
  78. •  Signature
  79. chevron_right  corto_compare
  80. •  Signature
  81. chevron_right  corto_scope_size
  82. •  Signature
  83. chevron_right  corto_scope_claim
  84. •  Signature
  85. •  See also
  86. chevron_right  corto_scope_release
  87. •  Signature
  88. •  See also
  89. chevron_right  corto_scope_walk
  90. •  Signature
  91. •  See also
  92. subject  Virtual Store

    Access and populate the virtual store.

  93. chevron_right  corto_select
  94. •  Signature
  95. chevron_right  corto_select fluent methods
  96. •  from
  97. •  format
  98. •  offset
  99. •  limit
  100. •  type
  101. •  instanceof
  102. •  instance
  103. •  mount
  104. •  fromNow
  105. •  fromTime
  106. •  toNow
  107. •  toTime
  108. •  forDuration
  109. •  slimit
  110. •  soffset
  111. •  yield_unknown
  112. •  iter
  113. •  resume
  114. •  iter_objects
  115. •  count
  116. chevron_right  corto_subscribe
  117. •  Signature
  118. chevron_right  corto_subscribe fluent methods
  119. •  from
  120. •  disabled
  121. •  dispatcher
  122. •  instance
  123. •  format
  124. •  type
  125. •  yield_unknown
  126. •  mount
  127. •  callback
  128. chevron_right  corto_unsubscribe
  129. •  Signature
  130. chevron_right  corto_publish
  131. •  Signature
  132. •  See also
  133. subject  Reflection

    Access to metadata of in-memory objects.

  134. chevron_right  corto_typeof
  135. •  Signature
  136. •  See also
  137. chevron_right  corto_stateof
  138. •  Signature
  139. •  See also
  140. chevron_right  corto_attrof
  141. •  Signature
  142. •  See also
  143. chevron_right  corto_isorphan
  144. •  Signature
  145. chevron_right  corto_isbuiltin
  146. •  Signature
  147. chevron_right  corto_isresumed
  148. •  Signature
  149. chevron_right  corto_countof
  150. •  Signature
  151. •  See also
  152. chevron_right  corto_idof
  153. •  Signature
  154. •  See also
  155. chevron_right  corto_nameof
  156. •  Signature
  157. •  See also
  158. chevron_right  corto_parentof
  159. •  Signature
  160. •  See also
  161. chevron_right  corto_sourceof
  162. •  Signature
  163. •  See also
  164. chevron_right  corto_check_state
  165. •  Signature
  166. •  See also
  167. chevron_right  corto_check_attr
  168. •  Signature
  169. •  See also
  170. chevron_right  corto_instanceof
  171. •  Signature
  172. •  See also
  173. chevron_right  corto_type_instanceof
  174. •  Signature
  175. •  See also
  176. chevron_right  corto_fullpath
  177. •  Signature
  178. •  See also
  179. chevron_right  corto_path
  180. •  Signature
  181. •  See also
  182. chevron_right  corto_childof
  183. •  Signature
  184. •  See also
  185. chevron_right  corto_owned
  186. •  Signature
  187. •  See also
  188. subject  Serialization

    Serialize values from and to registered formats.

  189. chevron_right  corto_serialize
  190. •  Signature
  191. •  See also
  192. chevron_right  corto_deserialize
  193. •  Signature
  194. •  See also
  195. chevron_right  corto_serialize_value
  196. •  Signature
  197. •  See also
  198. chevron_right  corto_deserialize_value
  199. •  Signature
  200. •  See also
  201. chevron_right  corto_fmt_lookup
  202. •  Signature
  203. subject  Security

    Secure data in the object store.

  204. chevron_right  corto_login
  205. •  Signature
  206. •  See also
  207. chevron_right  corto_logout
  208. •  Signature
  209. •  See also
  210. chevron_right  corto_set_session
  211. •  Signature
  212. •  See also
  213. chevron_right  corto_get_session
  214. •  Signature
  215. •  See also
  216. chevron_right  corto_authorize
  217. •  Signature
  218. •  See also
  219. chevron_right  corto_authorize_id
  220. •  Signature
  221. •  See also
  222. chevron_right  corto_useradd
  223. •  Signature
  224. •  See also
  225. chevron_right  corto_userdel
  226. •  Signature
  227. •  See also
  228. chevron_right  corto_secured
  229. •  Signature
  230. subject  Value Writer

    Metadata-based writing of data for deserializers.

  231. chevron_right  corto_rw_init
  232. •  Signature
  233. chevron_right  corto_rw_deinit
  234. •  Signature
  235. chevron_right  corto_rw_next
  236. •  Signature
  237. chevron_right  corto_rw_has_next
  238. •  Signature
  239. chevron_right  corto_rw_count
  240. •  Signature
  241. chevron_right  corto_rw_append
  242. •  Signature
  243. chevron_right  corto_rw_index
  244. •  Signature
  245. chevron_right  corto_rw_field
  246. •  Signature
  247. chevron_right  corto_rw_push
  248. •  Signature
  249. chevron_right  corto_rw_pop
  250. •  Signature
  251. chevron_right  corto_rw_in_scope
  252. •  Signature
  253. chevron_right  corto_rw_get_scope_type
  254. •  Signature
  255. chevron_right  corto_rw_get_type
  256. •  Signature
  257. chevron_right  corto_rw_get_member
  258. •  Signature
  259. chevron_right  corto_rw_get_index
  260. •  Signature
  261. chevron_right  corto_rw_get_ptr
  262. •  Signature
  263. chevron_right  corto_rw_set_value
  264. •  Signature
  265. chevron_right  corto_rw_set_bool
  266. •  Signature
  267. chevron_right  corto_rw_set_char
  268. •  Signature
  269. chevron_right  corto_rw_set_int
  270. •  Signature
  271. chevron_right  corto_rw_set_uint
  272. •  Signature
  273. chevron_right  corto_rw_set_float
  274. •  Signature
  275. chevron_right  corto_rw_set_string
  276. •  Signature
  277. chevron_right  corto_rw_set_ref
  278. •  Signature
  279. subject  Value Reader

    Metadata-based reading of values for serializers.

  280. chevron_right  corto_walk
  281. •  Signature
  282. •  See also
  283. chevron_right  corto_walk_value
  284. •  Signature
  285. •  See also
  286. chevron_right  corto_walk_ptr
  287. •  Signature
  288. •  See also
  289. chevron_right  corto_walk_members
  290. •  Signature
  291. •  See also
  292. chevron_right  corto_walk_elements
  293. •  Signature
  294. •  See also
  295. chevron_right  corto_walk_observable
  296. •  Signature
  297. •  See also
  298. chevron_right  corto_walk_init
  299. •  Signature
  300. •  See also
  301. chevron_right  corto_walk_deinit
  302. •  Signature
  303. •  See also
  304. chevron_right  corto_metawalk
  305. •  Signature
  306. •  See also
  307. chevron_right  corto_walk_constants
  308. •  Signature
  309. •  See also
  310. chevron_right  corto_walk_cases
  311. •  Signature
  312. •  See also
  313. subject  Value

    Supporting API for describing corto values.

  314. chevron_right  corto_value_typeof
  315. •  Signature
  316. •  See also
  317. chevron_right  corto_value_ptrof
  318. •  Signature
  319. •  See also
  320. chevron_right  corto_value_ptrset
  321. •  Signature
  322. •  See also
  323. chevron_right  corto_value_objectof
  324. •  Signature
  325. •  See also
  326. chevron_right  corto_value_field
  327. •  Signature
  328. •  See also
  329. chevron_right  corto_value_unaryOp
  330. •  Signature
  331. •  See also
  332. chevron_right  corto_value_binaryOp
  333. •  Signature
  334. •  See also
  335. chevron_right  corto_value_cast
  336. •  Signature
  337. •  See also
  338. chevron_right  corto_value_init
  339. •  Signature
  340. chevron_right  corto_value_object
  341. •  Signature
  342. chevron_right  corto_value_base
  343. •  Signature
  344. chevron_right  corto_value_ptr
  345. •  Signature
  346. chevron_right  corto_value_mem
  347. •  Signature
  348. chevron_right  corto_value_member
  349. •  Signature
  350. chevron_right  corto_value_constant
  351. •  Signature
  352. chevron_right  corto_value_element
  353. •  Signature
  354. chevron_right  corto_value_mapElement
  355. •  Signature
  356. chevron_right  corto_value_literal
  357. •  Signature
  358. chevron_right  corto_value_bool
  359. •  Signature
  360. chevron_right  corto_value_char
  361. •  Signature
  362. chevron_right  corto_value_uint
  363. •  Signature
  364. chevron_right  corto_value_int
  365. •  Signature
  366. chevron_right  corto_value_float
  367. •  Signature
  368. chevron_right  corto_value_string
  369. •  Signature
  370. chevron_right  corto_value_null
  371. •  Signature
  372. chevron_right  corto_value_unit
  373. •  Signature
  374. chevron_right  corto_value_unitof
  375. •  Signature
  376. chevron_right  corto_value_to_boolean
  377. •  Signature
  378. chevron_right  corto_value_to_character
  379. •  Signature
  380. chevron_right  corto_value_to_int
  381. •  Signature
  382. chevron_right  corto_value_to_uint
  383. •  Signature
  384. chevron_right  corto_value_to_float
  385. •  Signature
  386. chevron_right  corto_value_to_string
  387. •  Signature
  388. subject  Pointer

    Low level API for native pointers.

  389. chevron_right  corto_ptr_new
  390. •  Signature
  391. •  See also
  392. chevron_right  corto_ptr_free
  393. •  Signature
  394. •  See also
  395. chevron_right  corto_mem_new
  396. •  Signature
  397. •  See also
  398. chevron_right  corto_mem_free
  399. •  Signature
  400. •  See also
  401. chevron_right  corto_mem_typeof
  402. •  Signature
  403. •  See also
  404. chevron_right  corto_mem_deserialize
  405. •  Signature
  406. •  See also
  407. chevron_right  corto_ptr_resize
  408. •  Signature
  409. •  See also
  410. chevron_right  corto_ptr_count
  411. •  Signature
  412. •  See also
  413. chevron_right  corto_ptr_str
  414. •  Signature
  415. •  See also
  416. chevron_right  corto_ptr_copy
  417. •  Signature
  418. chevron_right  corto_ptr_unaryOp
  419. •  Signature
  420. •  See also
  421. chevron_right  corto_mem_unaryOp
  422. •  Signature
  423. •  See also
  424. chevron_right  corto_ptr_binaryOp
  425. •  Signature
  426. •  See also
  427. chevron_right  corto_ptr_cast
  428. •  Signature
  429. •  See also
  430. chevron_right  corto_ptr_compare
  431. •  Signature
  432. chevron_right  corto_ptr_init
  433. •  Signature
  434. •  See also
  435. chevron_right  corto_ptr_deinit
  436. •  Signature
  437. •  See also
generated with ♥ by corto/doc

Corto API Reference


In-memory Store

The in-memory store is a thread-safe, high-performance hierarchical object store that is designed to store the current state of an application. The store implements familiar OOP concepts like inheritance and polymorphism, alongside with support for collections, composite and primitive types to provide a convenient environment for expressing application logic.

Once objects are in the store, they can be discovered and introspected. This enables connecting generic components to the store, like for example a REST API, that automatically provides access to the contents of the store.

The object store provides a simple but powerful security framework for restricting access to objects. The security framework is deeply embedded into the core, thus decreasing the performance penalty to a minimum.

All objects are strongly typed, meaning their types can't change after they are created, although dynamic programming is supported by the any type. Type information is stored in the in-memory store alongside regular objects. This enables using the regular store APIs to create and query the store for metadata.

The in-memory store provides refcounting-based memory management. To maintain its realtime characteristics, the store will not attempt to detect reference-cycles in realtime. It is up to the application to ensure that non-persistent objects do not contain cycles.

Objects can be updated and observed. Every lifecycle event triggers a notification that can be catched by an observer (or subscriber, see vstore). Creating, updating and deleting objects all trigger notifications. Applications can subscribe for a single object, an object scope (branch) or a (sub)tree of objects.

The in-memory store interacts with the virtual store when lifecycle events take place. When the value of an object updates, it will be synchronized with the virtual store. When an object is created or deleted, it will also be created or deleted in the virtual store.

Corto makes an important distinction between deleting an object and no longer having references to an object. When the last reference to an object is removed, an object may be removed from the in-memory store to conserve RAM, but it will still be in the virtual store. A consecutive lookup of the object will reinsert it into the in-memory store.

Objects in the store are first declared, then defined. Between declaring and defining an application has the opportunity to set the initial object value. This ensures that when observers receive a DEFINE notification, the object will be set to a valid value. This also allows an application to forward- declare objects, which enables declaratively creating object cycles.

When defining an object, the virtual store is queried for the last value of the object. This is also referred to as resuming an object. The initial value assigned by the application inbetween declaring and defining the object may be overwritten when the vstore has a previous state of the object. This enables transparent persisting & retrieving of objects.

Applications may use the corto_create function to create an object with default values. The corto_create function is essentially a convenience wrapper around corto_declare and corto_define. When an object is defined it acquires the VALID object state, indicating that the value of the object may be interpreted for application logic.

Multiple threads may attempt to set the initial value of an object. When the same object is declared by multiple threads, corto_declare ensures that only one thread will see the object in a not-VALID state. While the object is undefined, corto_declare will block for the other threads, until the thread that received the non-VALID object defines the object.

When changing the value of an object, an application must use corto_update_begin and corto_update_end, which write-locks an object. When calling corto_update_end an UPDATE notification is sent to all observers of the object.

The store provides lifecycle hooks for objects, which are callbacks defined on the type of an object that provide more control to an object over its lifecycle. An example of a hook is the construct callback, which is invoked when an object is defined. Another hook is the validate hook, which allows the object to verify if a new object value is valid.

Applications can define functions and methods in the store, which can be implemented in multiple languages. The store provides an APO ( invoke.h) for registering language bindings, which allows to insert custom logic when a function object is invoked. This enables components written in multiple languages to interact with each other in a single process, which can for example be utilized to import Lua or Python scripts, whilst abstracting from the language they are written in. By default store functions are implemented in C. The store uses libffi for dynamically invoking C functions.

corto_create


Create a new named object.

Equivalent to calling corto_declare + corto_define.

Signature

corto_object
corto_create(
    corto_object parent,
    const char *id,
    corto_type type)

parent

The parent for the new object.

id

The object id. If NULL, a random unique id is generated. A name may contain multiple elements, separated by the '/' character. If one or more elements do not yet exist, they are created with the specified type.

type

The type of the object to create.

return

The new object, NULL if failed.

See also

corto_declare


Declare a new object.

This function returns an object in the DECLARED state, which enables setting the object value before invoking the type constructor with corto_define. When the object already exists with the specified type, the existing object will be returned.

The function fails if the type initializer fails or if it violates constraints of the specified type on the state or type of the specified parent. The function also fails when the object already exists with a different type.

Scoped objects are added to the scope of their parent and have a unique id which makes them discoverable in the object store. When this function succeeds an DECLARE event is emitted.

This function will block if there is another thread that has declared, but not defined the same object. Once the other thread defines the object, the function will unblock, and return an object in the DEFINED state. The calling thread can (and should) check the state of the returned object using corto_check_state to determine if it needs to initialize the object. The same thread may declare an object multiple times before it is defined.

Signature

corto_object
corto_declare(
    corto_object parent,
    const char *id,
    corto_type type)

parent

The parent for the new object.

id

The object id. If NULL, a random unique id is generated. A name may contain multiple elements, separated by the '/' character. If one or more elements do not yet exist, they are created with the specified type.

type

The type of the object to create.

return

The new object, NULL if failed.

See also

corto_define


Define an object.

This function changes the state of an object to DEFINED. When an object is defined, the type constructor is invoked. If successful, an DEFINE event is emitted. The DEFINE event indicates the moment when the value of an object is ready to be interpreted by contexts other than the one where the object was being created.

This function may emit an RESUME event instead of DEFINE if a SINK mount indicates that it has a copy of the object available. In this case, the function will overwrite the initial object value with the value that the SINK mount provides.

This mechanism enables transparent persistency of objects. The value specified by the application is treated as an initial value which is overridden by the latest value of the SINK, which is typically some form of persistent storage.

This function will fail if the type constructor fails.

If the function fails, the object is left in an undefined, invalid state. An application can attempt again to define the object by calling corto_define again on the object after resolving the issue that caused it to fail.

Signature

int16_t
corto_define(
    corto_object o)

o

The object to be defined.

return

0 if success, nonzero if failed.

See also

corto_delete


Delete an object.

This function deletes an object. If the object was DEFINED, the type destructor will be invoked.

Deleting an object does not guarantee that its memory is freed, as there still may be references to the object. Once all references have been released, the object will be deallocated.

If a named object is deleted, all it's children will be recursively deleted as well, using a depth-first walk.

This function fails if the current context does not own the object.

Signature

int16_t
corto_delete(
    corto_object o)

o

The object to be deleted.

return

0 if success, nonzero if failed.

See also

corto_update


Update an object.

This function emits an UPDATE event for the specified object.

This function fails if the current context does not own the object or if the object passed to was not created with ATTR_OBSERVABLE.

Signature

int16_t
corto_update(
    corto_object o)

o

The object to be updated.

return

0 if success, nonzero if failed.

See also

corto_update_begin


Start updating an object.

This function locks the object for thread-safe updating. No event is emitted yet. This function must be followed up by corto_update_end or corto_update_cancel.

This function fails if the current context does not own the object or if the object passed to was not created with ATTR_OBSERVABLE.

Signature

int16_t
corto_update_begin(
    corto_object o)

o

The object to be updated.

return

0 if success, nonzero if failed.

See also

corto_update_end


Update an object.

This function emits an UPDATE event and must be called after either a successful call to corto_update_begin or corto_update_try. If the function is called without first calling corto_update_begin or corto_update_try the behavior is undefined. The function will unlock the object.

This function behaves like corto_define when the object is not yet defined, in that it defines the object, and may either emit DEFINE or RESUME, depending on whether a SINK mount has a copy of the object.

Signature

int16_t
corto_update_end(
    corto_object o)

o

The object to be updated.

return

0 if success, nonzero if failed.

See also

corto_update_cancel


Cancel updating an object.

This function unlocks the object without any other side-effects. The application is responsible for reversing any changes made to the object.

Signature

int16_t
corto_update_cancel(
    corto_object o)

o

The object for which the update must be cancelled.

return

0 if success, nonzero if failed.

See also

corto_invalidate


Invalidate an object.

This function emits an INVALIDATE event when a valid object is passed to it. This function is typically used to indicate that an object has gone stale, or that the constructor of the object has failed.

This function fails if the current context does not own the object.

Signature

int16_t
corto_invalidate(
    corto_object o)

o

The object to be invalidated

return

0 if success, nonzero if failed.

See also

corto_claim


Claim an object.

This function increases the reference count of an object, which will prevent it from being deallocated.

It is usually not needed to call this function manually. When setting a member of a reference type, use the corto_set_ref function.

Signature

int32_t
corto_claim(
    corto_object o)

o

The object of which to increase the reference count.

return

The reference count of the object after the operation.

See also

corto_release


Release an object.

This function decreases the reference count of an object. When the reference count reaches zero, it will be deallocated.

Signature

int32_t
corto_release(
    corto_object o)

o

The object of which to increase the reference count.

return

The reference count of the object after the operation.

See also

corto_lookup


Lookup an object.

This function looks up an object and obtains a reference to it. If the object is not loaded in the store but is provided by a mount, it will be resumed from the mount into the store. After the object is no longer needed, an application should call corto_release.

corto_lookup can be used to find overloaded functions by specifying an parameter list between parentheses that contains the required types. For example, to find a function called add with two int32 parameters, 'add(int32,int32)' can be specified in id.

The following operators can be used in the parameter list: & - The requested argument is a reference. && - The offered argument must be a reference. null - The requested argument is either a reference or a string (null value). ? - The type is unknown.

Signature

corto_object
corto_lookup(
    corto_object scope,
    const char *id)

scope

The scope in which to lookup the object.

id

An id expression (foo/bar) identifying the object to lookup.

return

The object if found, NULL if not found.

See also

corto_resolve


Resolve an object.

This function is similar to corto_lookup, but follows a set of rules that is used to lookup types. Note however that corto_resolve can be used to lookup any object, not just types.

The reason that types use a different set of lookup rules is to enable short identifiers for builtin types (int32, struct, class, etc) and to types / packages in the corto package. Because these are frequently used, using an optimized set of rules will reduce footprint of type identifiers, which can significantly impact memory usage and bandwidth usage that rely on exchange of type information.

The rules of corto_resolve are: 1. If the identifier starts with an '/', lookup in root and return result. 2. If not, look for the identifier in corto/lang. 3. If not found, look for the identifier in the specified scope. 4. If not found, look for the identifier in the parent of the current scope [repeat] 5. If not found, look for the identifier in /corto.

corto_resolve will never look twice in a path, so if scope is corto/lang, the function will only look in corto/lang once.

If the id expression contains {}, corto_resolve will create an anonymous object by deserializing the contents within {} according to the rules of the corto string format.

Signature

corto_object
corto_resolve(
    corto_object scope,
    const char *id)

scope

The scope in which to lookup the object.

id

An id expression (foo/bar) identifying the object to lookup.

return

The object if found, NULL if not found.

See also

corto_observe


Create an observer.

Observers enable an application to listen for events from the object store, such as objects that are being created, updated or deleted. Observers can observe a single object, an object scope or a subtree of objects. corto_observe accepts a parameter event of the corto_eventMask type, which has the following values:

Flag Value Kind Description
CORTO_DECLARE 0x1 infra Observe objects being forward declared.
CORTO_DEFINE 0x2 data Observe objects being defined.
CORTO_DELETE 0x4 data Observe objects being deleted.
CORTO_INVALIDATE 0x8 data Observe objects being invalidated.
CORTO_UPDATE 0x10 data Observe objects being updated.
CORTO_RESUME 0x20 infra Observe objects being resumed.
CORTO_SUSPEND 0x40 infra Observe objects being suspended.
CORTO_ON_SELF 0x80 scope Observe a single object.
CORTO_ON_SCOPE 0x100 scope Observe children of an object.
CORTO_ON_TREE 0x200 scope Observe children of an object recursively.
CORTO_ON_VALUE 0x400 async Observe value of an object (requires lock).
CORTO_ON_METAVALUE 0x800 async Observe metavalue of an object.
CORTO_ON_ANY 0xffff any Observe all notifications.

The flag kinds have the following meaning:

Kind Description
infra Inform application about (meta) data in the RAM object store.
data Inform application about data (CrUD) events.
scope Set the scope of a mask.
async Set whether the mask requires an object to be locked.
any Enable all flags.

The functionality of corto_observe is further extended by fluent methods. See corto_observe fluent methods). A call to corto_observe must always finish with the callback fluent method, which creates the observer and accepts a callback that will be invoked when a matching notification triggers.

Observers provide a very fast mechanism for delivering events. The tradeoff is that for an observer to work, objects must be stored in RAM, which is fine if you don't observe millions of objects at the same time.

If you want to observe big datasets, check out corto_subscribe which offers equivalent functionality, but does not require objects to be stored in RAM.

Signature

corto_observe__fluent
corto_observe(
    corto_eventMask event,
    corto_object observable)

event

A mask that specifies the events to observe.

observable

The object to observe.

corto_observe fluent methods


The following methods extend the functionality of corto_observe by appending them to a call like this: corto_observe(...).<method>(...). Multiple methods can be appended to the call, as long as the previous method returns an instance of corto_observe__fluent.

disabled

Create disabled observer.

Disabled observers allow an application to make modifications to the observer mask or observable, and to observe multiple objects using corto_observer_observe.

Signature

corto_observe__fluent
disabled(
    void)

dispatcher

Provide dispatcher for observer.

Dispatchers intercept events before they are delivered to an observer callback, which enables applications to implement custom event handlers. A common usecase for this is to forward events to a worker thread.

Signature

corto_observe__fluent
dispatcher(
    corto_dispatcher dispatcher)
dispatcher

A dispatcher object.

instance

Specify an instance.

Instances are passed to observer callbacks. They are typically used to pass the this variable when an observer is associated with a class.

Signature

corto_observe__fluent
instance(
    corto_object instance)
instance

A corto object.

type

Filter objects by type.

The observer will only trigger on objects of the specified type.

Signature

corto_observe__fluent
type(
    char *type)
type

A valid corto type identifier.

callback

Specify callback, create observer.

Provide a callback function that is invoked when a matching event occurs. This function returns a new observer based on the specified parameters.

Signature

___
callback(
    void(
    *r)(
    corto_observer_event *))
callback

An observer callback function.

See also

corto_unobserve


Delete an observer.

No more events will be delivered to the callback after this function is called. Note that the observer object will not be deallocated if there are references to the object.

When there are still events in flight when this function is called (something that can happen when a dispatcher is pushing events to another thread) the application can prevent delivery of the event by checking the state of the observer object, which is part of the corto_observer_event instance, by doing:

void myDispatcher_post(corto_observer_event *e) {
    if (!corto_check_state(e->observer, CORTO_DELETED)) {
        corto_event_handle(e);
    } else {
        // Do nothing
    }
}

Signature

int16_t
corto_unobserve(
    corto_observer observer)

observer

An observer object.

return

0 if success, -1 if failed.

See also

corto_read_begin


Read-lock object.

This guarantees that the object will not be modified while the application holds the readlock. Multiple threads may obtain a readlock at the same time.

Signature

int16_t
corto_read_begin(
    corto_object o)

o

The object to readlock.

return

0 if success, non-zero if failed.

See also

corto_read_end


Release readlock.

Release lock on an object previously locked by corto_read_begin.

Signature

int16_t
corto_read_end(
    corto_object o)

o

The object to unlock.

return

0 if success, non-zero if failed.

See also

corto_lock


Write-lock object.

This guarantees that the object will not be read while the application holds the writelock, and that no other threads are modifying the object. Only one thread may hold a writelock at the same time.

Signature

int16_t
corto_lock(
    corto_object o)

o

The object to readlock.

return

0 if success, non-zero if failed.

See also

corto_unlock


Release writelock.

Release lock on an object previously locked by corto_write_begin.

Signature

int16_t
corto_unlock(
    corto_object o)

o

The object to unlock.

return

0 if success, non-zero if failed.

See also

corto_set_attr


Set object attributes for the current thread.

This function sets the attributes of objects that will be created in the current thread. For valid attribute values see the corto/lang/attr type.

Attributes were introduced to reduce footprint of corto objects by disabling features that are not used. For example, if an object does not need to be observed, it can be created without the CORTO_ATTR_OBSERVABLE attribute.

Signature

corto_attr
corto_set_attr(
    corto_attr attr)

attr

A mask containing the attributes for the current thread.

return

The previous attribute mask for this thread.

See also

corto_get_attr


Get the object attributes for the current thread.

This function returns the current object attributes that are set for this thread.

Signature

corto_attr
corto_get_attr(
    void)

return

The object attributes for the current thread.

See also

corto_set_source


Set the source for the current thread.

Signature

corto_object
corto_set_source(
    corto_object source)

source

A valid object.

return

The previous source of the thread.

See also

corto_get_source


Get the source for the current thread.

Signature

corto_object
corto_get_source(
    void)

return

The source of the current thread.

See also

corto_copy


Deep-copy value of source object to destination object.

The function accepts a pointer to an object reference. If the pointer points to a NULL value, the function will create a new object.

If the pointer contains a reference to an object, the function will verify if the type of the destination object is compatible with the source object. If it is not compatible, the function will fail.

Signature

int16_t
corto_copy(
    corto_object *dst,
    corto_object src)

dst

A pointer to the destination object.

src

The source object.

return

0 if success, non-zero if failed.

corto_compare


Compare value of two objects.

This function can be used to perform ordering on objects, as it will return whether objects are lesser, equal or larger than the other object.

Signature

int
corto_compare(
    corto_object o1,
    corto_object o2)

o1

The object to compare.

o2

The object to compare with.

return

0 if equal, 1 if o1 is larger than o2, -1 if o1 is smaller than o2.

corto_scope_size


Returns the number of child objects in a scope.

The objects passed to this function must be created with CORTO_ATTR_NAMED. If an object without CORTO_ATTR_NAMED is passed to this function the behavior is undefined.

This function must be used with care as it only returns number of objects that are currently loaded in the object store. If there are mounted objects in this scope that are not loaded in the store they will not be counted. To obtain an accurate count, use corto_select().count().

Signature

uint32_t
corto_scope_size(
    corto_object o)

o

A named object.

return

The number of objects in the scope of the object.

corto_scope_claim


Returns a sequence with the objects in the current scope.

The object passed to this function must be created with CORTO_ATTR_NAMED. If an object without CORTO_ATTR_NAMED is passed to this function the behavior is undefined.

This function must be used with care as it only returns objects that are currently loaded in the object store. If there are mounted objects in this scope that are not loaded in the store they will not be returned. To obtain a full list of objects count, use corto_select().iter_objects().

Signature

corto_objectseq
corto_scope_claim(
    corto_object o)

o

A named object.

return

A sequence with the objects in the scope of the object.

See also

corto_scope_release


Release a sequence obtained by corto_scope_claim.

Signature

void
corto_scope_release(
    corto_objectseq scope)

scope

A sequence obtained by corto_scope_claim.

See also

corto_scope_walk


Invoke a callback for each object in a scope.

The object passed to this function must be created with CORTO_ATTR_NAMED. If an object without CORTO_ATTR_NAMED is passed to this function the behavior is undefined.

Usage of this function is generally NOT recommended as it locks the scope which is a very intrusive operation. The lock is still being held when the action is called, so care must be taken not to introduce any deadlocks while in the action.

Use this function only for fast, low-level operations. For all other operations that need to walk a scope, use the safer corto_scope_claim and corto_scope_release.

Signature

int16_t
corto_scope_walk(
    corto_object o,
    corto_scope_walk_cb action,
    void *userData)

o

A named object.

return

A sequence with the objects in the scope of the object.

See also

Virtual Store

The virtual store is, as the name suggests, not an actual store, but provides uniform access to data from any number of 3rd party stores. Data in the virtual store can move transparently to and from the in-memory store when application interest emerges or goes away. This process is fully automated, and does not require explicit action on behalf of the application.

The virtual store is populated by 'mounts'. Mounts are entities which connect subtrees of objects into the virtual store, which is represented to the application as a single uniform tree. Operations on the virtual store are translated by the query engine to the appropriate mounts, which will then either retrieve or synchronize the requested operation from the query engine.

Subtrees provided by mounts may be mounted in different locations by different applications. The query engine automatically translates between local identifiers and mount identifiers, so that a mount does not require knowledge about how it connects to the virtual store.

The mount class provides a rich interface for interacting with many kinds of data. The interface is implemented as a set of overridable methods on the mount class which a mount may or may not implement, based on the capabilities of the underlying technology.

A mount can reply to a single request for data, be notified of subscriptions so it can provide realtime data, provide historical data, synchronize data from the store, batch data from the store, downsample data from the store, throttle an application (using an intelligent algorithm that evenly spaces delays across sampling periods), amongst others.

Mounts are, just like anything else, objects that are stored in the in-memory store. This means that mounts can be instantiated with the regular store API, and that mount configurations can be provided in any serialization format that corto supports (XML, JSON, CX, ...).

Applications can interact with the virtual store directly through the corto_select, corto_subscribe and corto_publish APIs. Rather than going through the object store, these functions communicate directly with the mounts.

Mounts use the same mechanisms to communicate with each other, which means that the in-memory store can be completely bypassed. This particularly speeds up scenarios where data is bridged, where two can forward directly from one to another. Mounts can optionally configure a serialization format, in which case corto will automatically serialize/deserialize data to the correct format when it arrives/leaves the mount. When two mounts communicate directly and the serialization format is the same, a quick pass-through will take place.

Mounts inherit from corto subscribers, which means that they use the same mechanisms to describe data that they synchronize. Subscribers in corto use a corto_query, which is a custom query format optimized for querying hierarchies. The two most important parts of a corto_query are the select and from fields. The select field specifies a filter that is matched against an object id. The from field specifies the location in the virtual store where the subscriber subscribes to. Identifiers of objects delivered to the subscriber will be relative to the from query field.

A mount uses the from field to determine where it will mount its data. This also ensures that data the mount receives is relative to its mount point, which allows a mount to abstract away from where it is mounted by the app.

corto_select


Single-shot query.

With corto_select an application can select a subset of objects using a corto identifier expression (parent, expr). The functionality of the corto_select function is extended with fluent methods (see corto_select fluent methods) that enable an application to further narrow down results and perform various operations on the objects.

The most common operation is to request an iterator to the matching objects which allows the application to iterate over the set one by one.

The corto_select function is designed to be an API that enables accessing large datasets with constrained resources. The iterative design of the API allows the corto mount implementations to feed data to the application one object at a time, so that even with large result sets, the memory of an application will not be exhausted. Furthermore the API has native support for pagination, which allows applications to further narrow down results.

The results returned by corto_select are in abitrary order, which is a result of the requirement of being able to deal with large datasets. Ordering results would require obtaining a full resultset before anything can be returned to the application, which is not scalable.

The performance of corto_select highly depends on the implementation of a mount. The backend provides as much information as possible upfront to the mount about which information is required, which allows a mount to prefetch/cache results. A mount may choose to implement such optimizations, but this is not enforced.

The function employs minimal locking on the object store while an application is iterating over a resultset. Outside of the corto_iter_next and corto_iter_hasNext calls no locks will be held, which enables applications to run corto_select queries concurrently and without disturbing other tasks in an application.

Signature

corto_select__fluent
corto_select(
    const char *expr,...)

expr

An expression matching one or more objects [printf-style format specifier].

corto_select fluent methods


The following methods extend the functionality of corto_select by appending them to a call like this: corto_select(...).<method>(...). Multiple methods can be appended to the call, as long as the previous method returns an instance of corto_select__fluent.

from

Specify a relative scope for the query.

Signature

corto_select__fluent
from(
    const char *scope)
scope

A scope identifier.

format

Request results in a specific format.

Signature

corto_select__fluent
format(
    const char *format)
format

A MIME identifier identifying a format.

offset

Enable pagination by specifying an object offset.

Signature

corto_select__fluent
offset(
    corto_uint64 offset)
offset

Specifies from which nth object results should be returned.

limit

Enable pagination by specifying a limit to the number of objects returned.

Signature

corto_select__fluent
limit(
    corto_uint64 limit)
limit

Specifies the total number of results that should be returned.

type

Filter results by type.

Signature

corto_select__fluent
type(
    const char *filter)
filter

An id expression matching one or more types.

instanceof

Filter out results that are not an instance of specified type.

Signature

corto_select__fluent
instanceof(
    const char *type)
filter

An id expression matching a single type.

instance

Filter out results from a specific instance (mount).

This is typically useful when using corto_select from a mount, and the mount does not want to invoke itself.

Signature

corto_select__fluent
instance(
    corto_object instance)
instance

The instance object.

mount

Only return results for a specific mount.

This is typically useful when using corto_select from a mount, and the mount does not want to invoke itself.

Signature

corto_select__fluent
mount(
    corto_mount mount)
instance

The instance object.

fromNow

Request historical data starting from the current time.

Signature

corto_select__fluent
fromNow(
    void)

fromTime

Request historical data starting from fixed timestamp.

Signature

corto_select__fluent
fromTime(
    corto_time t)
t

The timestamp from which to return historical data.

toNow

Request historical data until now.

Signature

corto_select__fluent
toNow(
    void)

toTime

Request historical data until a fixed timestamp.

Signature

corto_select__fluent
toTime(
    corto_time t)
t

The timestamp until which to return historical data.

forDuration

Request historical data for a specific time window.

Signature

corto_select__fluent
forDuration(
    corto_time t)
t

The duration of the time window.

slimit

Request historical data for a specific number of samples.

Signature

corto_select__fluent
slimit(
    uint64_t limit)
limit

The number of samples per object.

soffset

Request historical starting from a specific sample.

Signature

corto_select__fluent
soffset(
    uint64_t offset)
offset

The offset from which to return samples.

yield_unknown

Return unknown objects.

An unknown object is used as a placeholder for a parent that has not yet been created explicitly while one or more children of the parent have been created.

Unknown objects by themselves do not conceptually represent data, and should not ordinarily be synchronized. Scenarios where an application might be interested in unknown objects is where it is not guaranteed that the hierarchy will be fully constructed, but applications still need to be able to discover paths to where potential child objects are (like in a tool that allows browsing the entire store).

Because it is not illegal for multiple mounts to return the same unknown object, disabling this filter may result in duplicate results. One mount may return a normal object, while another mount may return the same object identifier as unknown. Multiple unknown objects can also be returned.

Signature

corto_select__fluent
yield_unknown(
    )

iter

Return an iterator to the requested results.

Results are returned as corto_record instances. A corto_record contains metadata and when a content type is specified, a serialized value of an object. When using this function, no objects are created.

Signature

int16_t
iter(
    corto_recordIter *iter_out)
iter_out

A pointer to an iterator object.

return

0 if success, -1 if failed.

resume

Resume objects into the object store.

This function will resume objects in the object store.

Signature

int16_t
resume(
    void)
return

0 if success, -1 if failed.

iter_objects

Return an iterator to the requested objects.

This function will return results as anonymous objects. No objects will be created in the object store.

Signature

int16_t
iter_objects(
    corto_objectIter *iter_out)
iter_out

A pointer to an iterator object.

return

0 if success, -1 if failed.

count

Return the number of objects for a query.

This function requires a walk over all the returned results to determine the total number of objects.

Signature

int64_t
count(
    void)
return

-1 if failed, otherwise the total number of objects.

corto_subscribe


Create a realtime query.

Subscribers enable an application to listen for for events from the object store and events that come directly from mounts. Subscribers receive only data events (DEFINE, UPDATE, DELETE).

The difference between subscribers and observers is that while observers provide a reference to an object, a subscriber returns a corto_record, which contains metadata about the object, and when requested, a serialized value.

This means that a subscriber does not require objects to be stored in the in-memory object store, which makes it a better API for working with large datasets.

Signature

corto_subscribe__fluent
corto_subscribe(
    const char *expr,...)

expr

An expression matching one or more objects [printf-style format specifier].

corto_subscribe fluent methods


The following methods extend the functionality of corto_subscribe by appending them to a call like this: corto_subscribe(...).<method>(...). Multiple methods can be appended to the call, as long as the previous method returns an instance of corto_subscribe__fluent.

from

Specify a relative scope for the subscriber.

Signature

corto_subscribe__fluent
from(
    const char *scope)
scope

A scope identifier.

disabled

Create disabled subscriber.

Disabled observers allow an application to make modifications to the event mask or expression, and to observe multiple expressions using corto_subscriber_subscribe.

Signature

corto_subscribe__fluent
disabled(
    void)

dispatcher

Provide dispatcher for subscriber.

Dispatchers intercept events before they are delivered to an subscriber callback, which enables applications to implement custom event handlers. A common usecase for this is to forward events to a worker thread.

Signature

corto_subscribe__fluent
dispatcher(
    corto_dispatcher dispatcher)
dispatcher

A dispatcher object.

instance

Specify an instance.

Instances are passed to subscriber callbacks. They are typically used to pass the this variable when an subscriber is associated with a class.

Signature

corto_subscribe__fluent
instance(
    corto_object instance)
instance

A corto object.

format

Request results in a specific format.

Signature

corto_subscribe__fluent
format(
    const char *format)
format

A MIME identifier identifying a format.

type

Filter objects by type.

The subscriber will only trigger on objects of the specified type.

Signature

corto_subscribe__fluent
type(
    const char *type)
type

A valid corto type identifier.

yield_unknown

Return unknown objects.

For a description of this function, see corto_select. This setting only affects behavior of the subscriber during alignment, when it calls corto_select.

Signature

corto_subscribe__fluent
yield_unknown(
    void)

mount

Create a mount of the specified type.

Signature

___
mount(
    corto_class type,
    const char *value)
type

A mount type.

value

A corto string to set additional members of the mount.

return

A new mount object

callback

Specify callback, create subscriber.

Provide a callback function that is invoked when a matching event occurs. This function returns a new subscriber based on the specified parameters.

Signature

___
callback(
    void(
    *r)(
    corto_subscriber_event *))
callback

An subscriber callback function.

corto_unsubscribe


Delete a subscriber.

No more events will be delivered to the callback after this function is called. Note that the subscriber object will not be deallocated if there are references to the object.

When there are still events in flight when this function is called (something that can happen when a dispatcher is pushing events to another thread) the application can prevent delivery of the event by checking the state of the subscriber object, which is part of the corto_subscriber_event instance, by doing:

void myDispatcher_post(corto_subscriber_event *e) {
    if (!corto_check_state(e->subscriber, CORTO_DELETED)) {
        corto_event_handle(e);
    } else {
        // Do nothing
    }
}

Signature

int16_t
corto_unsubscribe(
    corto_subscriber subscriber,
    corto_object instance)

subscriber

A subscriber object.

return

0 if success, -1 if failed.

corto_publish


Publish event.

This function enables emitting events for objects that are not loaded in the RAM store. This allows for efficient routing of events between subscribers without the need to (de)marshall object values.

If the object is loaded in the RAM store, a call to corto_publish will demarshall the specified value into the object.

The function may only emit events of the data kind, which are DEFINE, UPDATE, INVALIDATE and DELETE. The other events are reserved for objects that are loaded in the RAM store.

Signature

int16_t
corto_publish(
    corto_eventMask event,
    const char *id,
    const char *type,
    const char *format,
    void *content)

event

The event to be emitted

id

A string representing the id of the object in the form of 'foo/bar'.

type

A string representing the id of the type as returned by corto_fullpath.

format

A string representing the content type (format) of the specified value.

value

A string (or binary value) representing the serialized value of the object.

return

0 if success, nonzero if failed.

See also

Reflection

corto_typeof


Get the type of an object.

Signature

corto_type
corto_typeof(
    corto_object o)

o

The object for which to obtain the type.

return

The object type.

See also

corto_stateof


Obtain the current state mask of the object.

Object state changes as an object is declared, defined and ultimately deleted.

Signature

corto_state
corto_stateof(
    corto_object o)

o

The object of which to obtain the state.

return

The state mask of the current object.

See also

corto_attrof


Obtain the attribute mask of the object.

Object attributes are static after an object is declared.

Signature

corto_attr
corto_attrof(
    corto_object o)

o

The object of which to obtain the attributes.

return

The attribute mask of the current object.

See also

corto_isorphan


Check if an object is an orphan.

Orphans are objects that contain a reference to a parent object, but the parent object does not have the object in its scope.

Signature

bool
corto_isorphan(
    corto_object o)

o

The object to check

return

true if the object is an orphan. =

corto_isbuiltin


Check if an object is a builtin object.

Builtin objects are part of the corto runtime and are not located on the heap.

Signature

bool
corto_isbuiltin(
    corto_object o)

o

The object to check

return

true if the object is builtin.

corto_isresumed


Check if an object is a auto-resumed object.

Resumed objects are not created by the application through a corto_declare, but have been automatically resumed by, for example, a lookup function. Resumed objects may at any point become suspended again when there are no more references to them. Because of this, automatically resumed objects do not receive an initial refcount of 1 as is the case with regular named objects.

To ensure that memory is being properly released, corto keeps track of which objects are automatically resumed. Only PERSISTENT objects can be resumed.

Signature

bool
corto_isresumed(
    corto_object o)

o

The object to check

return

true if the object is automatically resumed.

corto_countof


The current reference count of the object.

This function should be used with caution, as it introduces dependencies on the underlying garbage collection mechanism. A valid use for this function would be in testcases, where it can be used to validate if an specific operation did not introduce any leaks.

Signature

int32_t
corto_countof(
    corto_object o)

o

The object for which to obtain the reference count.

return

The reference count of the object.

See also

corto_idof


Get the object id.

The object passed to this function must be created with CORTO_ATTR_NAMED. If an object without CORTO_ATTR_NAMED is passed to this function the behavior is undefined.

Signature

char*
corto_idof(
    corto_object o)

o

A named object for which to obtain the id.

return

The object id. The returned string is not owned by the application.

See also

corto_nameof


Get the object name.

The object passed to this function must be created with CORTO_ATTR_NAMED. If an object without CORTO_ATTR_NAMED is passed to this function the behavior is undefined.

The object name is the same as the object id, unless the 'nameof' function of a type is overridden, in which case the result of that function is used.

Object names are meant to provide a user friendly, though not necessarily unique way to refer to an object.

Signature

char*
corto_nameof(
    corto_id str,
    corto_object o)

str

An id buffer in which to store the name. If NULL, a corto-managed string is returned which may change with subsequent calls to corto_nameof and other functions that use the corto stringcache.

o

A named object for which to obtain the name.

return

The object name. If str is NULL, the returned string is not owned by the application. Otherwise, str is returned.

See also

corto_parentof


Get the parent of an object.

The object passed to this function must be created with CORTO_ATTR_NAMED. If an object without CORTO_ATTR_NAMED is passed to this function the behavior is undefined.

This function may return NULL if the corto root object is passed as argument. If

Signature

corto_object
corto_parentof(
    corto_object o)

o

The object for which to obtain the id.

return

The object id. The returned string is not owned by the application.

See also

corto_sourceof


Returns the source for an object.

Only objects created with CORTO_ATTR_PERSISTENT can explicitly set a source. If the object is not PERSISTENT and is an orphan the function will obtain the source of the parent. In all other scenarios the function will return NULL.

Signature

corto_object
corto_sourceof(
    corto_object o)

o

A valid object.

return

The source of the object.

See also

corto_check_state


Check if an object is of a specified state.

Object state changes as an object is declared, defined and ultimately deleted.

Signature

bool
corto_check_state(
    corto_object o,
    corto_state state)

o

The object for which to check the state.

state

The state to look for.

return

true if the object is in the specified state, otherwise false.

See also

corto_check_attr


Check if an object is of a specified attribute.

Object attributes are static after an object is declared.

Signature

bool
corto_check_attr(
    corto_object o,
    corto_attr attr)

o

The object for which to check the attribute.

state

The attribute to look for.

return

true if the object has the specified attribute, otherwise false.

See also

corto_instanceof


Check if object is an instance of a specified type.

This function returns true when types exactly match, when o is of a type that is a subtype of type, when o is of a type that implements type, and when o is of target{type}.

Signature

bool
corto_instanceof(
    corto_type type,
    corto_object o)

type

The type against which to check.

o

The object to check.

return

true if o is an instance of type, otherwise false.

See also

corto_type_instanceof


Check if objects of a type are an instance of another type.

Signature

bool
corto_type_instanceof(
    corto_type type,
    corto_type valueType)

type

The type against which to check.

valueType

The type to check.

return

true if objects of valueType are an instance of type, otherwise false.

See also

corto_fullpath


Obtain a full path identifier to an object.

This function returns the shortest path that will lead to resolving the object using a corto_resolve where the root is specified as scope.

In practice this means that for objects in corto/lang it will only return the object id (int32) while for all other objects the function will a forward slash ('/') separated list of ids as obtained by corto_idof (/grandparent/parent/object).

Signature

char*
corto_fullpath(
    corto_id str,
    corto_object o)

str

An id buffer in which to store the id. If NULL, a corto-managed string is returned which may change with subsequent calls to corto_fullpath and other functions that use the corto stringcache.

o

The object for which to obtain the id.

return

The full path. If str is NULL, the returned string is not owned by the application. Otherwise, str is returned.

See also

corto_path


Obtain a relative path identifier to an object.

This function returns the shortest path from the specified from object to the to object, separated by sep. If to is a parent of from, this function will insert the appropriate number of '..' operators. This function uses corto_idof to determine the object ids.

The result of this function can be used with corto_lookup to lookup the to object, where from is specifed as scope and result as id.

If NULL is specified for from, an initial forward slash will be added to the resulting path. If root_o is specified for from, no initial slash will be added to the resulting path.

Signature

char*
corto_path(
    corto_id str,
    corto_object from,
    corto_object to,
    const char *sep)

str

An id buffer in which to store the id. If NULL, a corto-managed string is returned which may change with subsequent calls to corto_fullpath and other functions that use the corto stringcache.

from

The object from the path should be offset.

o

The object to which to generate the path.

sep

The path separator.

return

The path. If str is NULL, the returned string is not owned by the application. Otherwise, str is returned.

See also

corto_childof


Check if object is a child of the specified parent.

The objects passed to this function must be created with CORTO_ATTR_NAMED. If an object without CORTO_ATTR_NAMED is passed to this function the behavior is undefined.

Signature

bool
corto_childof(
    corto_object p,
    corto_object o)

p

The parent object.

o

The child object.

return

true if o is a child of p, otherwise false.

See also

corto_owned


Check if object is owned by current thread.

Corto uses this function to check if a thread is allowed to change an object through corto_update or corto_delete functions. The rules for sourceship are as follows:

  • If the object source is NULL, the object is owned by the application. A SOURCE mount will not be able to modify the object. 2. If the object source is not NULL and not an instance of corto/vstore/mount, the rule 1 applies. This mode can be used to emit notifications from a non-mount instance without an observer for that instance receiving the notification. 3. If the object source is an instance of corto/vstore/mount, the mount owns the object. If the mount is a SINK, it shares sourceship with the application. If the mount is a SOURCE, only that mount will be able to change the object.

The source is determined as specified by corto_sourceof.

Signature

bool
corto_owned(
    corto_object o)

o

A valid object.

return

The source of the object.

See also

Serialization

corto_serialize


Serialize object to a registered serialization format.

This serializes an object and its metadata to a registered serialization format. Serialization formats are packages stored in driver/fmt.

Signature

char*
corto_serialize(
    corto_object o,
    const char *fmtId)

o

The object to serialize.

fmtId

The serialization format identifier (for example: text/json).

return

The serialized value.

See also

corto_deserialize


Deserialize object from a registered serialization format.

This deserializes a value in a registered serialization format to an object. The function accepts a pointer to an object reference, which may be NULL. If the pointer is NULL, a new object will be created.

If the pointer is not NULL and the serialized data does not match with the specified object identifier or type, the function will fail.

Signature

int16_t
corto_deserialize(
    void *o,
    const char *fmtId,
    const char *data)

o

Pointer to the object to deserialize into. Object may be NULL.

fmtId

The serialization format identifier (for example: text/json).

data

Value formatted in the specified serialization format.

return

0 if success, non-zero if failed.

See also

corto_serialize_value


Serialize object value to a registered serialization format.

This serializes an object value to a registered serialization format. This function does not serialize object metadata, like type and id. Serialization formats are packages stored in driver/fmt.

Signature

char*
corto_serialize_value(
    corto_object o,
    const char *fmtId)

o

The object to serialize.

fmtId

The serialization format identifier (for example: text/json).

return

The serialized value.

See also

corto_deserialize_value


Deserialize object value from a registered serialization format.

This deserializes a value in a registered serialization format to an object.

Signature

int16_t
corto_deserialize_value(
    corto_object o,
    const char *fmtId,
    const char *data)

o

The object to deserialize into.

fmtId

The serialization format identifier (for example: text/json).

data

Value formatted in the specified serialization format.

return

0 if success, non-zero if failed.

See also

corto_fmt_lookup


Obtain handle to a serialization format plugin.

This function provides a high(er) performance alternative to looking up serialization formats by id, by returning a handle to a format that can be reused.

Signature

corto_fmt
corto_fmt_lookup(
    const char *fmtId)

fmtId

The serialization format identifier.

return

Handle to a serialization format plugin. NULL if failed.

Security

corto_login


Login to a new session.

A login creates a new session, identified by a session token. After logging in the session is not yet active. To activate a session, pass the session token to the corto_set_session function.

A typical example of a session token can be an API key.

Signature

char*
corto_login(
    const char *username,
    const char *password)

username

The username of the user logging in.

password

The password of the user logging in.

return

The session token if login is valid. NULL if the login failed.

See also

corto_logout


Logout of a session.

After logging out, a session token is no longer guaranteed to authenticate a user.

Signature

void
corto_logout(
    const char *token)

token

An existing session token.

See also

corto_set_session


Set active session.

This sets the global session variable for the corto process. All authorization requests will use the specified session token.

Certain corto mechanisms (like subscribers) are associated with their own session token that they obtained at creation time. This allows a corto process to be multi-tenant.

Signature

char*
corto_set_session(
    const char *token)

token

An existing session token.

return

The previous session token.

See also

corto_get_session


Get active session.

This gets the global session variable for the corto process.

Signature

char*
corto_get_session(
    void)

return

The current session token.

See also

corto_authorize


Authorize the current session for an action on an object.

Signature

bool
corto_authorize(
    corto_object object,
    corto_secure_actionKind action)

o

The object for which to authorize.

action

The action to authorize.

return

true when authorized, false when not authorized.

See also

corto_authorize_id


Authorize the current session for an action on an object identifier.

Signature

bool
corto_authorize_id(
    const char *id,
    corto_secure_actionKind access)

id

The object identifier for which to authorize.

action

The action to authorize.

return

true when authorized, false when not authorized.

See also

corto_useradd


Register a new user.

Signature

int16_t
corto_useradd(
    const char *userId,
    const char *password,
    const char *group,
    const char *home)

userId

The user identifier.

password

The password for the user.

group

The group of the user.

home

The home scope of the user.

return

0 when success, non-zero when failed.

See also

corto_userdel


Unregister a user.

Signature

int16_t
corto_userdel(
    const char *userId)

userId

The user identifier.

return

0 when success, non-zero when failed.

See also

corto_secured


Test if process is secured.

This function provides a quick check to see if the process is secured. If the process is not secured, security-related functions will fail, and all requests for authorization are disabled.

Signature

bool
corto_secured(
    void)

return

true when secured, false when not secured.

Value Writer

This API enforces the rules of the corto typesystem, and offers a consistent way to refer to individual fields inside objects. It is therefore the recommended API for writing (de)serializers and other APIs that interact with object values.

The API allows applications to either iterate over fields in a value, or to jump to specific locations. The API provides access to any corto type.

Complex (composite/collection) values need to be pushed before they can be accessed. This opens the scope of the complex value, which allows iteration over the members/elements in that scope. It also will make field expressions relative to that scope. Pushing/popping scopes is analogous to the () and [] operators in cortoscript, as can be seen in this example:

Line l = {start:{x:10, 20}, stop.x:30, stop.y:40}

In this example, each { corresponds with a push, and each } corresponds with a pop. The example also illustrates how to set single fields in nested scopes without pushing/popping. This can be done in the reader/writer API with the field function.

Note that this is an UNSTABLE API.

corto_rw_init


Initialize a reader/writer.

Signature

corto_rw
corto_rw_init(
    corto_type type,
    void *ptr)

type

The type of the value that is read/written to.

ptr

The pointer to the value that is read/written to.

return

An initialized reader/writer value.

corto_rw_deinit


Deinitialize an reader/writer.

Signature

void
corto_rw_deinit(
    corto_rw *_this)

this

The reader/writer.

corto_rw_next


Move the cursor to next field.

This function will move the cursor to the next field. In the case of a composite value, this will be the next member. The member order is established by the order in which members are defined. If modifiers are specified on members, like READONLY or PRIVATE, such members will be skipped.

If the current type is a collection type, this will move the reader/writer to the next element in the collection. If the reader/writer hits the end of the collection, and the collection is growable (sequences, lists) a new element will automatically be added to the collection. To use a reader/writer to just walk over existing elements, use this function with has_next.

When this function is used on composite scopes, it will require a member cache to be initialized once for the current scope.

Signature

int16_t
corto_rw_next(
    corto_rw *_this)

this

The reader/writer.

return

0 if success, non-zero if failed.

corto_rw_has_next


Check if scope has a field after the cursor.

Use this function in combination with next to iterate over the existing fields in a reader/writer.

When this function is used on composite scopes, it will require a member cache to be initialized once for the current scope.

Signature

bool
corto_rw_has_next(
    corto_rw *_this)

this

The reader/writer.

return

true if there is a next field, false if not.

corto_rw_count


Return number of fields in current scope.

This returns the number of fields in the current scope, which in the case of a composite value is the number of accessible members, and in the case of a collection is the number of existing elements.

When this function is used on composite scopes, it will require a member cache to be initialized once for the current scope.

Signature

int32_t
corto_rw_count(
    corto_rw *_this)

this

The reader/writer.

return

The number of fields in the current scope.

corto_rw_append


Append new element to current scope.

This function only applies to collection scopes. After appending, the cursor will be set to the new element.

Signature

int16_t
corto_rw_append(
    corto_rw *_this)

this

The reader/writer.

return

0 if success, non-zero if failed.

corto_rw_index


Move the cursor to the field at specified index.

This function moves the cursor to either a member or an element, depending on whether the current scope is of a composite or a collection type.

When this function is used on composite scopes, it will require a member cache to be initialized once for the current scope.

Signature

int16_t
corto_rw_index(
    corto_rw *_this,
    uint32_t index)

this

The reader/writer.

index

The index to which to move the cursor to.

return

0 if success, non-zero if failed.

corto_rw_field


Move to field by expression.

This function will move the reader/writer to the field as identified by the specified field expression. Field expressions can address both members and elements, and can refer to nested elements. A few examples:

  • foo
  • foo.bar
  • [1]
  • foo.bar[1]

This function does not rely on the internal cursor, and does thus not require a member cache when used in composite scopes. Using this function will move the cursor when the addressed field is in the same scope as the reader/writer, such that when get_index is called, it will return the index where the member is located.

When a field expression addresses a value in a nested scope (not the current scope) the scope of the reader/writer will not be changed. Instead, the cursor will be invalidated, so that subsequent usage of the cursor will require an explicit action to set the cursor to a defined position.

Signature

int16_t
corto_rw_field(
    corto_rw *_this,
    const char *field_expr)

this

The reader/writer.

field_expr

The expression identifying the field to read/write.

return

0 if success, non-zero if failed.

corto_rw_push


Enter scope of composite / collection field.

This will move the scope to the current field, if the current field is a complex (composite / collection) type. Pushing a scope enables the reader/writer to read/write to fields in a complex value.

Each scope has its own cursor. After pushing, the cursor for this scope is initialized to 0 (initial position) and all rw API functions will now operte on/relative to this scope.

When this function is invoked on a list type that is null, a new ll object will be assigned to the field.

To return to the previous scope, use the pop function.

Signature

int16_t
corto_rw_push(
    corto_rw *_this,
    bool as_collection)

this

The reader/writer.

as_collection

Force the scope to be a collection. Equivalent to [] operator.

return

0 if success, non-zero if failed.

corto_rw_pop


Leave scope of composite / collection field.

This will move the scope back to the parent scope. The cursor of the parent scope does not automatically progress to the next field. To move to the next field, an explicit call to corto_rw_next is needed.

Signature

int16_t
corto_rw_pop(
    corto_rw *_this)

this

The reader/writer.

return

0 if success, non-zero if failed.

corto_rw_in_scope


Check if readerwriter is in a pushed scope.

Signature

bool
corto_rw_in_scope(
    corto_rw *_this)

corto_rw_get_scope_type


Get type of current scope.

Signature

corto_type
corto_rw_get_scope_type(
    corto_rw *_this)

corto_rw_get_type


Get type of current field.

Signature

corto_type
corto_rw_get_type(
    corto_rw *_this)

corto_rw_get_member


Get member object of current field.

Signature

corto_member
corto_rw_get_member(
    corto_rw *_this)

corto_rw_get_index


Get index of current field.

Signature

int32_t
corto_rw_get_index(
    corto_rw *_this)

corto_rw_get_ptr


Get pointer of current field.

Signature

void*
corto_rw_get_ptr(
    corto_rw *_this)

corto_rw_set_value


Set current field to a corto_value.

Signature

uintptr_t
corto_rw_set_value(
    corto_rw *_this,
    corto_value *value)

corto_rw_set_bool


Assign a boolean to the current field.

Signature

uintptr_t
corto_rw_set_bool(
    corto_rw *_this,
    bool value)

corto_rw_set_char


Assign a character to the current field.

Signature

uintptr_t
corto_rw_set_char(
    corto_rw *_this,
    char value)

corto_rw_set_int


Assign an integer to the current field.

Signature

uintptr_t
corto_rw_set_int(
    corto_rw *_this,
    int64_t value)

corto_rw_set_uint


Assign an unsigned integer to the current field.

Signature

uintptr_t
corto_rw_set_uint(
    corto_rw *_this,
    uint64_t value)

corto_rw_set_float


Assign a signed integer to the current field.

Signature

uintptr_t
corto_rw_set_float(
    corto_rw *_this,
    double value)

corto_rw_set_string


Assign a string to the current field.

Signature

uintptr_t
corto_rw_set_string(
    corto_rw *_this,
    const char *value)

corto_rw_set_ref


Assign a reference to the current field.

Signature

uintptr_t
corto_rw_set_ref(
    corto_rw *_this,
    corto_object value)

Value Reader

The walk API provides functionality to dynamically walk over a corto value without requiring compile time knowledge of the values' type. The API allows for the creation of generic components that can translate corto values to other representations, like JSON, XML or an SQL statement.

The walk API accepts an instance of corto_walk_opt which contains two arrays of callbacks. The first array is called program, and contains callback that are invoked when values of a specific corto_typeKind (PRIMITIVE, COMPOSITE, COLLECTION, etc) are encountered. A member called reference contains a callback that is invoked when an object reference value is encountered.

The second array is called metaprogram and contains callbacks that are invoked when walking over a certain kind of meta-structure, expressed by corto_value_kind (OBJECT, MEMBER, ELEMENT, etc).

The walk API is recursively implemented, which means that to visit deeper levels of nesting, a walk method has to be invoked recursively. Scalar values represent the leaf nodes of the values to visit. To visit all values, callbacks in the metaprogram array must invoke corto_walk_value on the 'value' parameter of the callback. In the program array, the following typeKinds must invoke these functions respectively (if not specified, do not invoke anything):

  • CORTO_COMPOSITE: corto_walk_members
  • CORTO_COLLECTION: corto_walk_elements

When doing a metawalk, also invoke:

  • CORTO_PRIMITIVE: corto_walk_constants (for bitmask and enum types only)
  • CORTO_COMPOSITE: corto_walk_cases (for unions only)

In addition to callbacks, corto_walk_opt contains extra information to instruct the walk routine which values to serialize. The access and accessKind values determine which members the walk routine will visit. The access member specifies a mask of member modifiers which will be matched against the member modifiers (GLOBAL, LOCAL, PRIVATE, READONLY, etc). The accessKind member specifies the function used to match the modifier:

  • CORTO_NOT: visit members without any of the modifiers specified by access.
  • CORTO_OR: visit members with one or more modifiers specified by access.
  • CORTO_XOR: visit members that exactly match modifiers specified by access.

The corto_walk_opt type contains a members sequence that when populated, will restrict the visited members to those specified in the sequence.

The aliasAction member specifies what to do when an alias member is encountered:

  • CORTO_WALK_ALIAS_FOLLOW: follow alias members to the original member.
  • CORTO_WALK_ALIAS_IGNORE: ignore alias members
  • CORTO_WALK_ALIAS_PASSTHROUGH: visit alias members like ordinary members.

Corto types can, when inheriting from other types or on their own members, specify which parts of a type are be hidden. Hidden means that a member will not show up in ordered initializers. Ordered initializers are initializers where member values are specified in order of occurrence ({10, 20, 30}). The opposite is an unordered initializers, where members are initialized by name ({z=10 x=20 y=30}). With alias members, a user can unhide hidden members. By combining hidden and alias members, a user can exercise full control over the order in which members appear in ordered initializers. An example:

struct Foo:/
  u: int32
  v: int32, hidden
  w: int32

struct Bar: Foo, hidden
  alias x: Foo/u
  alias y: Foo/v
  z: int32

The initializers for Foo is {u, w}, whereas the initializer for Bar is {x, y, z} where x and y are an alias for Foo/u and Foo/v. The w member is not part of the ordered initializer for Bar, while the v member is not part of the ordered initializer for Foo.

Ordered initializers are used in many places in corto. For example, the Bar type uses an ordered initializer to set its base member to Foo (it could also have read struct Bar: base=Foo). Furthermore, ordered initializers are used in many generated functions where a value is initialized or set.

The optionalAction member specifies what to do when an optional member is encountered:

  • CORTO_WALK_OPTIONAL_IF_SET: only visit optional values when set.
  • CORTO_WALK_OPTIONAL_ALWAYS: always visit optional values.
  • CORTO_WALK_OPTIONAL_PASSTHROUGH: do not dereference optional values

Optional members in Corto are implemented as a pointer to the member type. If an optional member is not set, the member contains a NULL pointer. By default the walk routine dereferences optional values so that callbacks do not have to implement special logic to deal with optional values. In some cases however a walk routine needs access to the raw pointer, for example, when a member needs to be set/unset in a callback. For these scenario's, the CORTO_WALK_OPTIONAL_PASSTHROUGH feature can be used.

The visitAllCases member specifies whether the walk action should visit all union cases or only the active union case (determined by the discriminator). When invoking corto_metawalk, this value is automatically set to true.

A corto_walk_opt instance must always be initialized using the corto_walk_init function. By default all values of an object are visited.

corto_walk


Walk over a corto object.

Signature

int16_t
corto_walk(
    corto_walk_opt *opt,
    corto_object o,
    void *userData)

opt

Pointer to an initialized corto_walk_opt instance.

object

The object to be visited.

userData

A pointer that will be passed to the callbacks.

return

0 if success, non-zero if failed.

See also

corto_walk_value


Walk over a corto_value instance.

Signature

int16_t
corto_walk_value(
    corto_walk_opt *opt,
    corto_value *value,
    void *userData)

opt

Pointer to an initialized corto_walk_opt instance.

object

The corto_value instance to be visited.

userData

A pointer that will be passed to the callbacks.

return

0 if success, non-zero if failed.

See also

corto_walk_ptr


Walk over a native pointer.

Signature

int16_t
corto_walk_ptr(
    corto_walk_opt *opt,
    void *ptr,
    corto_type type,
    void *userData)

opt

Pointer to an initialized corto_walk_opt instance.

ptr

The pointer to be visited.

type

The type of the pointer.

userData

A pointer that will be passed to the callbacks.

return

0 if success, non-zero if failed.

See also

corto_walk_members


Walk over the members of a composite type.

This function should only be called from the CORTO_COMPOSITE callback in the program array of 'opt'.

Signature

int16_t
corto_walk_members(
    corto_walk_opt *opt,
    corto_value *value,
    void *userData)

opt

Pointer to an initialized corto_walk_opt instance.

value

The 'value' parameter passed to the CORTO_COMPOSITE callback.

userData

A pointer that will be passed to the callbacks.

return

0 if success, non-zero if failed.

See also

corto_walk_elements


Walk over the elements of a collection type.

This function should only be called from the CORTO_COLLECTION callback in the program array of 'opt'.

Signature

int16_t
corto_walk_elements(
    corto_walk_opt *opt,
    corto_value *value,
    void *userData)

opt

Pointer to an initialized corto_walk_opt instance.

value

The 'value' parameter passed to the CORTO_COLLECTION callback.

userData

A pointer that will be passed to the callbacks.

return

0 if success, non-zero if failed.

See also

corto_walk_observable


Walk an observable member.

This function should only be called from the callback specified for the 'observable' member of 'opt'.

Observable members introduce a level of indirection by creating an object of the member type, as opposed to inlining the member value. This function resolves this indirection so that subsequent walk functions will be presented with a pointer to the value, instead of the object. This allows walk callbacks to be agnostic about whether a member is observable.

Signature

int16_t
corto_walk_observable(
    corto_walk_opt *opt,
    corto_value *info,
    void *userData)

opt

Pointer to an initialized corto_walk_opt instance.

value

The 'value' parameter passed to the observable callback.

userData

A pointer that will be passed to the callbacks.

return

0 if success, non-zero if failed.

See also

corto_walk_init


Initialize a corto_walk_opt instance.

Signature

void
corto_walk_init(
    corto_walk_opt *opt)

opt

Pointer to corto_walk_opt struct.

See also

corto_walk_deinit


Deinitialize a corto_walk_opt instance.

Signature

int16_t
corto_walk_deinit(
    corto_walk_opt *opt,
    void *userData)

opt

Pointer to an initialized corto_walk_opt instance.

See also

corto_metawalk


Walk over a corto type.

This function creates a dummy object of the specified type, and then walks over this dummy object. It ensures that every potential value of the type is visited, which makes the function suitable for serializing types to type representations of other technologies, such as a CREATE TABLE statement or an XSD.

Signature

int16_t
corto_metawalk(
    corto_walk_opt *opt,
    corto_type type,
    void *userData)

opt

Pointer to an initialized corto_walk_opt instance.

type

The type to visit.

userData

A pointer that will be passed to the callbacks.

return

0 if success, non-zero if failed.

See also

corto_walk_constants


Walk over the constants of a bitmask/enumeration type.

This function should only be called from the CORTO_PRIMITIVE callback in the program array of 'opt', and only when serializing an instance of a bitmask or enumeration type.

In addition, this function should only be invoked when doing a corto_metawalk. Invoking this function in an ordinary corto_walk will result in undefined behavior.

Signature

int16_t
corto_walk_constants(
    corto_walk_opt *opt,
    corto_value *value,
    void *userData)

opt

Pointer to an initialized corto_walk_opt instance.

value

The 'value' parameter passed to the CORTO_PRIMITIVE callback.

userData

A pointer that will be passed to the callbacks.

return

0 if success, non-zero if failed.

See also

corto_walk_cases


Walk over the cases of a union type.

This function should only be called from the CORTO_COMPOSITE callback in the program array of 'opt', and only when serializing an instance of a union type.

In addition, this function should only be invoked when doing a corto_metawalk. Invoking this function in an ordinary corto_walk will result in undefined behavior.

Signature

int16_t
corto_walk_cases(
    corto_walk_opt *opt,
    corto_value *value,
    void *userData)

opt

Pointer to an initialized corto_walk_opt instance.

value

The 'value' parameter passed to the CORTO_COMPOSITE callback.

userData

A pointer that will be passed to the callbacks.

return

0 if success, non-zero if failed.

See also

Value

The corto_value type contains meta-information in addition to a pointer and a type that allows it to describe any possible value in corto. The most commonly used values are objects, members and elements.

The corto_walk API in particular uses corto_value to communicate meta information about the value that is visited. A corto_value instance can itself also be an input for the corto_walk API. The corto_value type also plays a prominent role in the format interface. Whenever a value that is potentially not an object needs to be shared between components, corto_value is the preferred carrier.

The functions that are available for corto_value allow an application to work with values of which the types are not known upfront. Beyond getting and setting values dynamically, applications can use the corto_value API to cast values dynamically, perform unary and binary operators and navigate and query all scalar values of a value encapsulated by corto_value.

In addition to describing corto values, a corto_value instance can also contain a literal value. Literal values can be used to represent constant values in unary or binary operations.

Each corto_value has a parent field which can point to another corto_value. This allows a corto_value to express a hierarchy of values, as is often found in nested (composite/collection) types. The walk API automatically populates the parent field so that walk callbacks have full access to all information about the value being serialized.

corto_value_typeof


Get the type of a corto_value.

Signature

corto_type
corto_value_typeof(
    corto_value *value)

value

A pointer to a corto_value.

return

The type of the specified value.

See also

corto_value_ptrof


Get a pointer of a corto_value.

The resulting pointer can be used in corto_ptr_* functions, together with the result of corto_value_typeof.

Signature

void*
corto_value_ptrof(
    corto_value *val)

value

A pointer to a corto_value.

return

A pointer to the value represented by the corto_value.

See also

corto_value_ptrset


Set the corto_value to a new pointer.

This function will not modify the value of the current pointer, but overrides the value encapsulated by the corto_value. For example, this function can set a corto_value to a new object, or new member.

It is important that the specified pointer is of the same type as the corto_value. It is illegal to set the pointer of a corto_value instance of the CORTO_LITERAL kind.

Signature

int16_t
corto_value_ptrset(
    corto_value *val,
    void *ptr)

value

A pointer to a corto_value.

ptr

The pointer to set for the corto_value.

return

0 if success, -1 if failed.

See also

corto_value_objectof


Return the object associated with a specified corto_value.

Most corto_value instances point to values in a corto_object. This object is stored as a separate field of the value, and can be obtained by this function.

The function is invalid for corto_value instances of the CORTO_LITERAL kind.

Signature

corto_object
corto_value_objectof(
    corto_value *val)

value

A pointer to a corto_value.

ptr

The pointer to set for the corto_value.

return

0 if success, -1 if failed.

See also

corto_value_field


Get a member from an existing composite corto_value.

Initialize a new corto_value from an existing corto_value with a member of the existing corto_value. The function accepts a member expression in the form of foo.bar.helloworld. If the specified member is not valid for the type of the corto_value instance, the function will fail.

Signature

int16_t
corto_value_field(
    corto_value *value,
    const char *member,
    corto_value *out)

value

A pointer to a corto_value.

member

A valid member expression for the type of the specified value.

out

The resulting corto_value.

return

0 if success, -1 if failed.

See also

corto_value_unaryOp


Perform unary operator on a corto_value.

The result corto_value has to at least be an initialized corto_value (use corto_value_init for new values). The value does not have to be of a matching type. If the result corto_value owned any resources, they will be deallocated / released before assigning the new value.

Signature

int16_t
corto_value_unaryOp(
    corto_operatorKind _operator,
    corto_value *value,
    corto_value *result)

_operator

The operator to perform.

value

A pointer to the operand corto_value.

result

A pointer to the result corto_value.

return

0 if success, nonzero if failed.

See also

corto_value_binaryOp


Perform binary operator on two corto_values.

The result corto_value has to at least be an initialized corto_value (use corto_value_init for new values). The value does not have to be of a matching type. If the result corto_value owned any resources, they will be deallocated / released before assigning the new value.

Signature

int16_t
corto_value_binaryOp(
    corto_operatorKind _operator,
    corto_value *left,
    corto_value *right,
    corto_value *result)

_operator

The operator to perform.

left

A pointer to the leftoperand corto_value.

right

A pointer to the right operand corto_value.

result

A pointer to the result corto_value.

return

0 if success, nonzero if failed.

See also

corto_value_cast


Cast a value.

Signature

int16_t
corto_value_cast(
    corto_value *src,
    corto_type dst_type,
    corto_value *result)

value

A pointer to the value to cast.

resultType

The type to cast to.

result

A corto_value pointer to the result of the cast.

return

0 if success, nonzero if failed.

See also

corto_value_init


Initialize a new corto_value instance.

Signature

corto_value
corto_value_init(
    void)

return

A corto_value instance of kind CORTO_POINTER with ptr set to NULL.

corto_value_object


Initialize a new corto_value instance holding an object.

A value representing an object in the corto object store.

Signature

corto_value
corto_value_object(
    corto_object object,
    corto_type type)

object

A valid object reference.

type

The type of the new corto_value. The type may be different from the object type, but the object has to be an instance of the specified type.

return

A new corto_value instance.

corto_value_base


Initialize a new corto_value instance holding a base value.

Base corto_value instances express the base value of a value that is of a type that uses inheritance. This kind is typically used by the corto_walk API when serializing the base of a value.

Making base a separate kind, allows applications to differentiate between the full value and a base value. Older versions of the walk API used a member kind to express inheritance where the member was set to NULL, but this complicated code and was less intuitive.

It is good practice to make the parent field of a BASE corto_value (eventually) point to a value of the CORTO_OBJECT kind for objects, or CORTO_POINTER for non-object values.

Signature

corto_value
corto_value_base(
    void *ptr,
    corto_type type)

ptr

A pointer to a value.

type

The type of the new corto_value.

return

A new corto_value instance.

corto_value_ptr


Initialize a new corto_value instance holding a generic value.

A value representing any value that does not fall in any of the other categories.

Signature

corto_value
corto_value_ptr(
    void *ptr,
    corto_type t)

ptr

A pointer to a value.

type

The type of the value.

return

A new corto_value instance.

corto_value_mem


Initialize a new corto_value instance holding a generic value.

Similar to corto_value_ptr, with the exception that if of a reference type, and encountered by a walk routine, the routine initiates a walk by value instead of invoking the reference callback.

Reference values are otherwise only walked by value if of valueKind CORTO_OBJECT. Reference types mandate that they are instantiated as objects which is consistent with this design.

However, in case of the 'ptr' format, values are communicated in a memory representation consistent with objects, but without the overhead of an actual object. To facilitate this usecase, a copy function is needed that can walk over the value of a non-object pointer of a reference type.

Value instances of kind CORTO_MEM explicitly do not have an associated object, which is another difference with values of the CORTO_POINTER kind.

Given the exotic nature of this functionality it is recommended that applications avoid it unless they have a keen understanding of what the implications are.

Signature

corto_value
corto_value_mem(
    void *ptr,
    corto_type t)

ptr

A pointer to a value.

type

The type of the value.

return

A new corto_value instance.

corto_value_member


Initialize a new corto_value instance holding a member value.

A value used to represent members of composite values.

Signature

corto_value
corto_value_member(
    corto_object object,
    corto_member member,
    void *ptr)

object

The object containing the member (can be NULL).

member

The member meta object.

ptr

A pointer to the member value.

type

The type of the value.

return

A new corto_value instance.

corto_value_constant


Initialize a new corto_value instance holding a constant value.

A value used to represent enumeration or bitmask constants. This is typically used by the metawalk API when serializing each constant of a bitmask or enumeration type.

Signature

corto_value
corto_value_constant(
    corto_object object,
    corto_constant *constant,
    void *value)

object

The object containing the constant (can be NULL).

constant

The constant meta object.

ptr

A pointer to the constant value.

return

A new corto_value instance.

corto_value_element


Initialize a new corto_value instance holding an element value.

A value used to represent elements in a collection value.

Signature

corto_value
corto_value_element(
    corto_object object,
    corto_type type,
    uint32_t index,
    void *ptr)

object

The object containing the element (can be NULL).

type

The type of the element.

index

The index of the element.

ptr

A pointer to the element value.

return

A new corto_value instance.

corto_value_mapElement


Initialize a new corto_value instance holding a map element value.

A value used to represent map elements in a collection value.

Signature

corto_value
corto_value_mapElement(
    corto_object object,
    corto_type type,
    corto_type keyType,
    void *key,
    void *ptr)

object

The object containing the element (can be NULL).

type

The type of the element.

keyType

The type of the key.

key

The key value

ptr

A pointer to the element value.

return

A new corto_value instance.

corto_value_literal


Initialize a new corto_value instance holding a literal.

A value used to represent a literal of a scalar type. This function copies the provided value into the corto_value structure.

Signature

corto_value
corto_value_literal(
    corto_literal_kind kind,
    void *ptr)

kind

A literal kind (CORTO_LITERAL_BOOLEAN, CORTO_LITERAL_CHARACTER, CORTO_LITERAL_INTEGER, CORTO_LITERAL_UNSIGNED_INTEGER, CORTO_LITERAL_FLOATING_POINT, CORTO_LITERAL_STRING or CORTO_LITERAL_NULL)

ptr

A pointer to the literal value.

return

A new corto_value instance.

corto_value_bool


Initialize a new corto_value instance holding a boolean literal.

Signature

corto_value
corto_value_bool(
    bool value)

value

A boolean value.

return

A new corto_value instance.

corto_value_char


Initialize a new corto_value instance holding a character literal.

Signature

corto_value
corto_value_char(
    corto_char value)

value

A character value.

return

A new corto_value instance.

corto_value_uint


Initialize a new corto_value instance holding an unsigned integer literal.

Signature

corto_value
corto_value_uint(
    corto_uint64 value)

value

An unsigned integer value.

return

A new corto_value instance.

corto_value_int


Initialize a new corto_value instance holding a signed integer literal.

Signature

corto_value
corto_value_int(
    corto_uint64 value)

value

A signed integer value.

return

A new corto_value instance.

corto_value_float


Initialize a new corto_value instance holding a floating point literal.

Signature

corto_value
corto_value_float(
    corto_float64 value)

value

A floating point value.

return

A new corto_value instance.

corto_value_string


Initialize a new corto_value instance holding a string literal.

This function copies the provided string into the corto_value structure.

Signature

corto_value
corto_value_string(
    char *value)

value

A string value.

return

A new corto_value instance.

corto_value_null


Initialize a new corto_value instance holding a null literal.

Signature

corto_value
corto_value_null(
    void)

return

A new corto_value instance.

corto_value_unit


Set the unit of a value.

This function only works for literal values.

Signature

int16_t
corto_value_unit(
    corto_value *value,
    char *unit)

value

A value.

unit

The unit to assign to the value.

return

zero if success, nonzero if failed.

corto_value_unitof


Get the unit for a value.

Signature

char*
corto_value_unitof(
    corto_value *value)

value

A value.

return

The unit string. NULL if value does not have a unit.

corto_value_to_boolean


Get value as bool.

Signature

int16_t
corto_value_to_boolean(
    corto_value *value,
    bool *out)

value

A value value.

return

An integer value.

corto_value_to_character


Get value as character.

Signature

int16_t
corto_value_to_character(
    corto_value *value,
    char *out)

value

A value value.

return

An integer value.

corto_value_to_int


Get value as signed integer.

Signature

int16_t
corto_value_to_int(
    corto_value *value,
    int64_t *out)

value

A value value.

return

An integer value.

corto_value_to_uint


Get value as signed integer.

Signature

int16_t
corto_value_to_uint(
    corto_value *value,
    uint64_t *out)

value

A value value.

return

An integer value.

corto_value_to_float


Get value as signed integer.

Signature

int16_t
corto_value_to_float(
    corto_value *value,
    double *out)

value

A value value.

return

An integer value.

corto_value_to_string


Get value as signed integer.

Signature

int16_t
corto_value_to_string(
    corto_value *value,
    char **out)

value

A value value.

return

An integer value.

Pointer

This API allows applications to utilize the corto typesystem with values that are either allocated on the stack or the heap. All API functions accept at least a pointer value and a corresponding type. The value pointed to by the pointer must be at least of the size prescribed by the type, and must contain a valid value.

For safe creation of values on heap or stack, use corto_ptr_new and corto_ptr_init. To ensure that an application does not leak memory, ensure to call corto_ptr_free for heap values created with corto_ptr_new, and call corto_ptr_deinit for stack/heap values initialized with corto_ptr_init.

corto_ptr_new


Allocate a new value on the heap.

This function allocates a new value on the heap that can hold the value of a corto type. If the specified type is a reference type, a pointer-sized value is returned. This function will invoke the initializer for the specified type.

Note that the result of this function is a plain heap object, not a corto object, so you cannot use functions that accept a corto_object instance.

To avoid memory leakage, the result of this function must be deallocated with corto_ptr_free.

Signature

void*
corto_ptr_new(
    corto_type type)

type

The type for which to create the value.

return

An initialized value on the heap for the specified type.

See also

corto_ptr_free


Deallocate a value allocated with corto_ptr_new.

This function deallocates a value allocated with corto_ptr_new and will invoke the deinitializer for the specified type.

Signature

void
corto_ptr_free(
    void *ptr,
    corto_type type)

type

The type of the value to be deallocated.

ptr

A pointer to the value.

See also

corto_mem_new


Allocate memory on the heap.

This function allocates memory on the heap that can hold the value of a corto type. In contrary to corto_ptr_new, if the type is a reference type, the function will not create a pointer but allocate the type size. This function will invoke the initializer for the specified type.

Note that the result of this function is a plain heap object, not a corto object, so you cannot use functions that accept a corto_object instance.

The result of this function can be used as a value for the binary/corto content type.

To avoid memory leakage, the result of this function must be deallocated with corto_ptr_free.

Signature

void*
corto_mem_new(
    corto_type type)

type

The type for which to create the value.

return

An initialized value on the heap for the specified type.

See also

corto_mem_free


Deallocate a value allocated with corto_mem_new.

This function deallocates a value allocated with corto_mem_new and will invoke the deinitializer for the specified type.

Signature

void
corto_mem_free(
    void *ptr)

ptr

A pointer to the value.

See also

corto_mem_typeof


Get type of a pointer allocated with corto_mem_new.

Signature

corto_type
corto_mem_typeof(
    void *ptr)

ptr

A pointer to the value.

See also

corto_mem_deserialize


Deserialize value into mem pointer.

Signature

int16_t
corto_mem_deserialize(
    void *ptr,
    const char *fmt,
    const void *value)

ptr

A pointer to the value.

fmt

Format of the serialized value.

value

The serialized value.

See also

corto_ptr_resize


Populate a collection with specified number of elements.

This function fills a collection with initialized elements. Depending on the kind of the collection the function will either populate an array, sequence or list. This function is not valid for map collection types.

If the provided collection is not empty, the existing elements will be deinitialized. Note that for array types the size is fixed, and if the function finds an existing array it won't do anything.

To free the resources, either call this function with size 0 or call the corto_ptr_free function.

This function may fail if the initializer of the elementType fails or if the specified size exceeds the bound of the collection type.

Signature

int16_t
corto_ptr_resize(
    void *ptr,
    corto_type type,
    uint32_t size)

ptr

A pointer to the collection

type

The type for which to initialize the collection.

size

The size to which to grow/shrink the collection.

return

0 if success, -1 if failed.

See also

corto_ptr_count


Return the number of elements in a type.

This function will return the number of elements in the specified pointer. If the pointer is of an array type, the function will always return the max size of the array. If the pointer is of any other collection type, the function will return the current size.

If this function is called on a non-collection type, it will return 1.

Signature

uint64_t
corto_ptr_count(
    void *ptr,
    corto_type type)

ptr

A pointer to the collection

type

The type for which to initialize the collection.

return

0 if success, -1 if failed.

See also

corto_ptr_str


Get a corto string representation for value.

This function is equivalent to calling corto_ptr_contentof with content type text/corto.

Signature

char*
corto_ptr_str(
    void *ptr,
    corto_type type,
    uint32_t maxLength)

ptr

A pointer to the value.

type

The type of the value.

maxLength

The type of the value.

return

A serialized corto string for the value. Must be deallocated with free.

See also

corto_ptr_copy


Copy value into another value.

Signature

int16_t
corto_ptr_copy(
    void *dst,
    corto_type type,
    void *src)

dst

A pointer to the destination value.

type

The type of the source and destination value.

src

A pointer to the source value.

return

0 if success, nonzero if failed.

corto_ptr_unaryOp


Perform unary operator on a value.

Signature

int16_t
corto_ptr_unaryOp(
    corto_type type,
    corto_operatorKind _operator,
    void *ptr,
    void *result)

type

The type of the value.

_operator

The operator to perform.

ptr

A pointer to the operand value.

result

A pointer to the result value.

return

0 if success, nonzero if failed.

See also

corto_mem_unaryOp


Perform unary operator on a value.

Signature

int16_t
corto_mem_unaryOp(
    corto_type type,
    corto_operatorKind _operator,
    void *ptr,
    void *result)

type

The type of the value.

_operator

The operator to perform.

ptr

A pointer to the operand value.

result

A pointer to the result value.

return

0 if success, nonzero if failed.

See also

corto_ptr_binaryOp


Perform binary operator with two values.

Signature

int16_t
corto_ptr_binaryOp(
    corto_type type,
    corto_operatorKind _operator,
    void *left,
    void *right,
    void *result)

type

The type of the left and right value.

_operator

The operator to perform.

left

A pointer to the left operand value.

A pointer to the right operand value.

result

A pointer to the result value.

return

0 if success, nonzero if failed.

See also

corto_ptr_cast


Cast a value.

Signature

int16_t
corto_ptr_cast(
    corto_type fromType,
    void *from,
    corto_type resultType,
    void *result)

fromType

The type of the value to cast.

from

A pointer to the value to cast.

resultType

The type to cast to.

result

A pointer to the result of the cast.

return

0 if success, nonzero if failed.

See also

corto_ptr_compare


Compare two values.

Both values must be instances of the same type.

Signature

corto_equalityKind
corto_ptr_compare(
    const void *ptr1,
    corto_type type,
    const void *ptr2)

ptr1

A pointer to the first value.

type

The type of the value.

ptr2

A pointer to the second value.

return

CORTO_EQ, CORTO_LT, CORTO_GT when ptr1 is equal, larger or greater than ptr2.

corto_ptr_init


Initialize a value.

This function is not needed when a value is allocated with corto_ptr_new. A valid example usecase for corto_ptr_init is when allocating a buffer for a sequence, and the new elements need to be initialized.

Signature

int16_t
corto_ptr_init(
    void *ptr,
    corto_type type)

ptr

A pointer to the value.

type

The type of the value.

return

0 if success, -1 if failed.

See also

corto_ptr_deinit


Deinitialize a value.

This function is not needed when a value is allocated with corto_ptr_new. A valid example usecase for corto_ptr_init is when deallocating a buffer for a sequence, and the elements need to be deinitialized.

Signature

int16_t
corto_ptr_deinit(
    void *ptr,
    corto_type type)

ptr

A pointer to the value.

type

The type of the value.

return

0 if success, -1 if failed.

See also