You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2020/04/20 13:25:36 UTC

[plc4x] 01/01: [WIP] Currently doesn't work - Rafactored the API into multiple smaller parts - Removed the callbacks again

This is an automated email from the ASF dual-hosted git repository.

cdutz pushed a commit to branch feature/c-api
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 36bcc4513796c6a59ac2dd82a1f2d12337ca0c73
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Mon Apr 20 15:25:11 2020 +0200

     [WIP] Currently doesn't work
     - Rafactored the API into multiple smaller parts
     - Removed the callbacks again
---
 sandbox/plc4c/api/src/main/include/plc4c.h         | 254 +--------------------
 .../src/main/include/plc4c_connection.h}           |  46 ++--
 .../src/main/include/{plc4c.h => plc4c_system.h}   |  87 +------
 .../src/main/include/plc4c_types.h}                |  57 +++--
 .../examples/hello-world/src/main/c/hello_world.c  |  21 +-
 .../{plc4c_private_types.c => plc4c_connection.c}  |  26 +--
 .../spi/src/main/c/{plc4c.c => plc4c_system.c}     |  37 +--
 .../c/{plc4c_private_types.c => plc4c_types.c}     |   8 +-
 8 files changed, 121 insertions(+), 415 deletions(-)

diff --git a/sandbox/plc4c/api/src/main/include/plc4c.h b/sandbox/plc4c/api/src/main/include/plc4c.h
index 46c6dc3..8b4038d 100644
--- a/sandbox/plc4c/api/src/main/include/plc4c.h
+++ b/sandbox/plc4c/api/src/main/include/plc4c.h
@@ -22,257 +22,11 @@
 extern "C" {
 #endif
 
-#include <stdbool.h>
+/* Convenience header file that just imports all the different parts of the API */
 
-
-/**
- * Public API
- */
-
-/**
- *
- * PLC4C error codes
-*/
-typedef enum error_code {
-    OK,
-    UNKNOWN_ERROR,
-    NO_MEMORY,
-    INVALID_CONNECTION_STRING,
-    NOT_REACHABLE,
-    PERMISSION_DENIED,
-    INTERNAL_ERROR
-} error_code;
-
-/**
- * Helper that translates from an error_code enum value to something a human can work with.
- *
- * @param err error code.
- * @return A human readable error description.
- */
-char *plc4c_error_code_to_error_message(error_code err);
-
-/**
- * the plc4c system
- */
-typedef struct plc4c_system_t plc4c_system;
-
-/**
- * the plc4c_driver
- */
-typedef struct plc4c_driver_t plc4c_driver;
-
-/**
- * the plc4c_connection
- */
-typedef struct plc4c_connection_t plc4c_connection;
-
-/**
- * SYSTEM CALLBACKS
- */
-
-/**
- * Function pointer for a callback called when a driver is loaded.
- * Set in plc4c_system @see plc4c_system_set_on_driver_loaded()
- * @param driver
- */
-typedef void (*plc4c_system_callback_on_driver_loaded)(plc4c_driver *driver);
-
-/**
- * Function pointer for a callback called when loading a driver fails.
- * Set in plc4c_system @see plc4c_system_set_on_driver_load_error
- * NOTE: driver_name could be a pointer to the configuration for the driver instead....
- * @param driver_name
- * @param error_code
- */
-typedef void (*plc4c_system_callback_driver_load_error)(const char *driver_name, error_code error);
-
-/**
- * Function pointer for a callback called when is successfully made
- * Set in plc4c_system @see plc4c_system_set_on_connection()
- * @param connection
- */
-typedef void (*plc4c_system_callback_on_connection)(plc4c_connection *connection);
-
-/**
- * Function pointer for a callback called when connecting fails.
- * Set in plc4c_system @see plc4c_system_set_on_connection_error
- * @param connection_string
- * @param error_code
- */
-typedef void (*plc4c_system_callback_connection_error)(const char *connection_string, error_code error);
-
-/**
- * Function pointer for a callback called when is successfully made
- * Set in plc4c_system @see plc4c_system_set_on_connection()
- * @param connection
- */
-typedef void (*plc4c_system_callback_on_disconnection)(plc4c_connection *connection);
-
-/**
- * Function pointer for a callback called when connecting fails.
- * Set in plc4c_system @see plc4c_system_set_on_connection_error
- * @param connection
- * @param error_code
- */
-typedef void (*plc4c_system_callback_disconnection_error)(plc4c_connection *connection, error_code error);
-
-/**
- * Function pointer for a callback called when a driver returns an error
- * @param driver
- * @param connection
- * @param error_code
- */
-typedef void(*plc4c_system_callback_loop_error)
-        (plc4c_driver *driver, plc4c_connection *connection, error_code error);
-
-/**
- * OTHER FUNCTION DEFS FOR SYSTEM
- */
-
-
-/**
- * SYSTEM FUNCTIONS
- */
-
-/**
- * Function to create a plc4c_system
- * @param system
- * @return NO_MEMORY if failed to create system
- */
-error_code plc4c_system_create(plc4c_system **system);
-
-/**
- * Function to destroy a plc4c_system
- * This will also destroy all connections associated with the system
- * @param system
- */
-void plc4c_system_destroy(plc4c_system *system);
-
-/**
- * Function to set the on_driver_loaded callback for the plc4c system
- * @param system
- * @param callback plc4c_system_callback_on_driver
- */
-void plc4c_system_set_on_driver_loaded(plc4c_system *system,
-                                       plc4c_system_callback_on_driver_loaded callback);
-
-/**
- * Function to set the error callback for loading drivers for the plc4c system
- * @param system
- * @param callback plc4c_system_callback_driver_load_error
- */
-void plc4c_system_set_on_driver_load_error(plc4c_system *system,
-                                           plc4c_system_callback_driver_load_error callback);
-
-/**
- * Function to set the on_connection callback for the plc4c system
- * @param system
- * @param callback plc4c_system_callback_on_connection
- */
-void plc4c_system_set_on_connection(plc4c_system *system,
-                                    plc4c_system_callback_on_connection callback);
-
-/**
- * Function to set the error callback for making connections for the plc4c system
- * @param system
- * @param callback plc4c_system_callback_connection_error
- */
-void plc4c_system_set_on_connection_error(plc4c_system *system,
-                                          plc4c_system_callback_connection_error callback);
-
-/**
- * Function to set the on_disconnection callback for the plc4c system
- * @param system
- * @param callback plc4c_system_callback_on_disconnection
- */
-void plc4c_system_set_on_disconnection(plc4c_system *system,
-                                       plc4c_system_callback_on_disconnection callback);
-
-/**
- * Function to set the error callback for shutting down connections for the plc4c system
- * @param system
- * @param callback
- */
-void plc4c_system_set_on_disconnection_error(plc4c_system *system,
-                                             plc4c_system_callback_disconnection_error callback);
-
-/**
- * Function to set the error callback loops
- * @param system
- * @param callback plc4c_system_callback_loop_error
- */
-void plc4c_system_set_on_loop_error(plc4c_system *system,
-                                    plc4c_system_callback_loop_error callback);
-
-/**
- * Function to initialize the PLC4C system (Initialize the driver manager and the list of enabled drivers)
- * @param system
- * @return error_code
- */
-error_code plc4c_init(plc4c_system *system);
-
-/**
- * Function to clean up the PLC4C system (Free any still used resources, terminate live connections, ...)
- * @param system
- */
-void plc4c_system_shutdown(plc4c_system *system);
-
-/**
- * Function to initialize a connection to a PLC by parsing the given connection string
- * and setting the passed connection system
- *
- * @param system
- * @param connectionString
- * @return error_code INVALID_CONNECTION_STRING, NO_MEMORY
- */
-error_code plc4c_system_connect(plc4c_system *system,
-                                const char *connectionString,
-                                plc4c_connection **connection);
-
-/**
- * Function to initialize a connection to a PLC by parsing the given connection string
- * and setting the passed connection system and also providing callbacks for success and
- * failure in case of problems.
- *
- * @param system
- * @param connectionString
- * @param connection
- * @param success_callback
- * @param error_callback
- * @return error_code INVALID_CONNECTION_STRING, NO_MEMORY
- */
-error_code plc4c_system_connect_callback(plc4c_system *system,
-                                         const char *connectionString,
-                                         plc4c_connection **connection,
-                                         plc4c_system_callback_on_connection success_callback,
-                                         plc4c_system_callback_connection_error error_callback);
-
-/**
- * Function to terminate a connection to a PLC.
- *
- * @param connection
- * @param plc4c_connection
- */
-error_code plc4c_disconnect(plc4c_connection *connection);
-
-/**
- * Function to terminate a connection to a PLC.
- *
- * @param connection
- * @param plc4c_connection
- */
-error_code plc4c_disconnect_callback(plc4c_connection *connection,
-                                     plc4c_system_callback_on_disconnection success_callback,
-                                     plc4c_system_callback_disconnection_error error_callback);
-
-/**
- * Function to give any drivers the chance to do their work.
- * In single-threaded environments we can't operate with event
- * handler loops as they would block the rest of the application.
- *
- * @return error_code
- */
-error_code plc4c_system_loop();
+#include "plc4c_types.h"
+#include "plc4c_system.h"
+#include "plc4c_connection.h"
 
 #ifdef __cplusplus
 }
diff --git a/sandbox/plc4c/spi/src/main/c/plc4c_private_types.c b/sandbox/plc4c/api/src/main/include/plc4c_connection.h
similarity index 56%
copy from sandbox/plc4c/spi/src/main/c/plc4c_private_types.c
copy to sandbox/plc4c/api/src/main/include/plc4c_connection.h
index 8de071a..a9043f7 100644
--- a/sandbox/plc4c/spi/src/main/c/plc4c_private_types.c
+++ b/sandbox/plc4c/api/src/main/include/plc4c_connection.h
@@ -16,25 +16,41 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+#ifndef PLC4C_CONNECTION_H_
+#define PLC4C_CONNECTION_H_
+#ifdef __cplusplus
+extern "C" {
+#endif
 
-#include "plc4c.h"
+#include <stdbool.h>
+#include "plc4c_types.h"
 
-/* private!! */
-
-struct plc4c_system_t {
-   /* drivers */
+/**
+ * CONNECTION CALLBACKS
+ */
 
-   /* connections */
+/**
+ * OTHER FUNCTION DEFS FOR CONNECTION
+ */
 
-   /* callbacks */
-};
+/**
+ * CONNECTION FUNCTIONS
+ */
 
-struct plc4c_driver_t {
-  /* name */
+/**
+ * Function to terminate a connection to a PLC.
+ *
+ * @param connection
+ * @param plc4c_connection
+ */
+error_code plc4c_connection_disconnect(plc4c_connection *connection);
 
-  /* ??? */
-};
+/**
+ * Get the connection string from a given connection.
+ */
+char* plc4c_connection_get_connection_string(plc4c_connection *connection);
 
-struct plc4c_connection_t {
- /* ???? */
-};
\ No newline at end of file
+#ifdef __cplusplus
+}
+#endif
+#endif //PLC4C_CONNECTION_H_
\ No newline at end of file
diff --git a/sandbox/plc4c/api/src/main/include/plc4c.h b/sandbox/plc4c/api/src/main/include/plc4c_system.h
similarity index 75%
copy from sandbox/plc4c/api/src/main/include/plc4c.h
copy to sandbox/plc4c/api/src/main/include/plc4c_system.h
index 46c6dc3..25c53ef 100644
--- a/sandbox/plc4c/api/src/main/include/plc4c.h
+++ b/sandbox/plc4c/api/src/main/include/plc4c_system.h
@@ -16,55 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-#ifndef PLC4C_H_
-#define PLC4C_H_
+#ifndef PLC4C_SYSTEM_H_
+#define PLC4C_SYSTEM_H_
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #include <stdbool.h>
-
-
-/**
- * Public API
- */
-
-/**
- *
- * PLC4C error codes
-*/
-typedef enum error_code {
-    OK,
-    UNKNOWN_ERROR,
-    NO_MEMORY,
-    INVALID_CONNECTION_STRING,
-    NOT_REACHABLE,
-    PERMISSION_DENIED,
-    INTERNAL_ERROR
-} error_code;
-
-/**
- * Helper that translates from an error_code enum value to something a human can work with.
- *
- * @param err error code.
- * @return A human readable error description.
- */
-char *plc4c_error_code_to_error_message(error_code err);
-
-/**
- * the plc4c system
- */
-typedef struct plc4c_system_t plc4c_system;
-
-/**
- * the plc4c_driver
- */
-typedef struct plc4c_driver_t plc4c_driver;
-
-/**
- * the plc4c_connection
- */
-typedef struct plc4c_connection_t plc4c_connection;
+#include "plc4c_types.h"
 
 /**
  * SYSTEM CALLBACKS
@@ -209,7 +168,7 @@ void plc4c_system_set_on_loop_error(plc4c_system *system,
  * @param system
  * @return error_code
  */
-error_code plc4c_init(plc4c_system *system);
+error_code plc4c_system_init(plc4c_system *system);
 
 /**
  * Function to clean up the PLC4C system (Free any still used resources, terminate live connections, ...)
@@ -230,42 +189,6 @@ error_code plc4c_system_connect(plc4c_system *system,
                                 plc4c_connection **connection);
 
 /**
- * Function to initialize a connection to a PLC by parsing the given connection string
- * and setting the passed connection system and also providing callbacks for success and
- * failure in case of problems.
- *
- * @param system
- * @param connectionString
- * @param connection
- * @param success_callback
- * @param error_callback
- * @return error_code INVALID_CONNECTION_STRING, NO_MEMORY
- */
-error_code plc4c_system_connect_callback(plc4c_system *system,
-                                         const char *connectionString,
-                                         plc4c_connection **connection,
-                                         plc4c_system_callback_on_connection success_callback,
-                                         plc4c_system_callback_connection_error error_callback);
-
-/**
- * Function to terminate a connection to a PLC.
- *
- * @param connection
- * @param plc4c_connection
- */
-error_code plc4c_disconnect(plc4c_connection *connection);
-
-/**
- * Function to terminate a connection to a PLC.
- *
- * @param connection
- * @param plc4c_connection
- */
-error_code plc4c_disconnect_callback(plc4c_connection *connection,
-                                     plc4c_system_callback_on_disconnection success_callback,
-                                     plc4c_system_callback_disconnection_error error_callback);
-
-/**
  * Function to give any drivers the chance to do their work.
  * In single-threaded environments we can't operate with event
  * handler loops as they would block the rest of the application.
@@ -277,4 +200,4 @@ error_code plc4c_system_loop();
 #ifdef __cplusplus
 }
 #endif
-#endif //PLC4C_H_
\ No newline at end of file
+#endif //PLC4C_SYSTEM_H_
\ No newline at end of file
diff --git a/sandbox/plc4c/spi/src/main/c/plc4c_private_types.c b/sandbox/plc4c/api/src/main/include/plc4c_types.h
similarity index 50%
copy from sandbox/plc4c/spi/src/main/c/plc4c_private_types.c
copy to sandbox/plc4c/api/src/main/include/plc4c_types.h
index 8de071a..99e2c35 100644
--- a/sandbox/plc4c/spi/src/main/c/plc4c_private_types.c
+++ b/sandbox/plc4c/api/src/main/include/plc4c_types.h
@@ -16,25 +16,50 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+#ifndef PLC4C_TYPES_H_
+#define PLC4C_TYPES_H_
+#ifdef __cplusplus
+extern "C" {
+#endif
 
-#include "plc4c.h"
-
-/* private!! */
-
-struct plc4c_system_t {
-   /* drivers */
+/**
+ *
+ * PLC4C error codes
+*/
+typedef enum error_code {
+    OK,
+    UNKNOWN_ERROR,
+    NO_MEMORY,
+    INVALID_CONNECTION_STRING,
+    NOT_REACHABLE,
+    PERMISSION_DENIED,
+    INTERNAL_ERROR
+} error_code;
 
-   /* connections */
+/**
+ * Helper that translates from an error_code enum value to something a human can work with.
+ *
+ * @param err error code.
+ * @return A human readable error description.
+ */
+char *plc4c_error_code_to_error_message(error_code err);
 
-   /* callbacks */
-};
+/**
+ * the plc4c system
+ */
+typedef struct plc4c_system_t plc4c_system;
 
-struct plc4c_driver_t {
-  /* name */
+/**
+ * the plc4c_driver
+ */
+typedef struct plc4c_driver_t plc4c_driver;
 
-  /* ??? */
-};
+/**
+ * the plc4c_connection
+ */
+typedef struct plc4c_connection_t plc4c_connection;
 
-struct plc4c_connection_t {
- /* ???? */
-};
\ No newline at end of file
+#ifdef __cplusplus
+}
+#endif
+#endif //PLC4C_TYPES_H_
\ No newline at end of file
diff --git a/sandbox/plc4c/examples/hello-world/src/main/c/hello_world.c b/sandbox/plc4c/examples/hello-world/src/main/c/hello_world.c
index 592cc75..50461c9 100644
--- a/sandbox/plc4c/examples/hello-world/src/main/c/hello_world.c
+++ b/sandbox/plc4c/examples/hello-world/src/main/c/hello_world.c
@@ -19,6 +19,14 @@
 #include <stdio.h>
 #include "../../../../../api/src/main/include/plc4c.h"
 
+void onConnectionSuccess(plc4c_connection *connection) {
+    printf("Connected to %s", plc4c_connection_get_connection_string(connection));
+}
+
+void onConnectionError(const char *connection_string, error_code error) {
+    printf("Error connecting to %s. Got error %s", connection_string, plc4c_error_code_to_error_message(error));
+}
+
 void onConnection2Success(plc4c_connection *connection) {
 
 }
@@ -33,16 +41,22 @@ int main() {
   plc4c_connection *connection1 = NULL;
   plc4c_connection *connection2 = NULL;
 
+  // Create a new uninitialized plc4c_system
   error_code error = plc4c_system_create(&system);
   if (error != OK) {
     return -1;
   }
 
-  error = plc4c_init(system);
+  // Initialize the plc4c_system (loading of drivers, setting up other stuff, ...)
+  error = plc4c_system_init(system);
   if (error != OK) {
     return -1;
   }
 
+  // Register the global callbacks.
+  plc4c_system_set_on_connection(system, &onConnectionSuccess);
+  plc4c_system_set_on_connection_error(system, &onConnectionError);
+
   // Establish connections to remote devices
   // you may or may not care about the connection handle
   error = plc4c_system_connect(system, "s7://192.168.42.20", &connection1);
@@ -50,8 +64,7 @@ int main() {
     return -1;
   }
 
-  error = plc4c_system_connect_callback(system, "s7://192.168.42.22", &connection2,
-          &onConnection2Success, &onConnection2Error);
+  error = plc4c_system_connect(system, "s7://192.168.42.22", &connection2);
   if (error != OK) {
     return -1;
   }
@@ -65,6 +78,8 @@ int main() {
 
   // Make sure everything is cleaned up correctly.
   plc4c_system_shutdown(system);
+
+  // Finally destroy the plc4c_system, freeing up all memory allocated by plc4c.
   plc4c_system_destroy(system);
 
   return 0;
diff --git a/sandbox/plc4c/spi/src/main/c/plc4c_private_types.c b/sandbox/plc4c/spi/src/main/c/plc4c_connection.c
similarity index 75%
copy from sandbox/plc4c/spi/src/main/c/plc4c_private_types.c
copy to sandbox/plc4c/spi/src/main/c/plc4c_connection.c
index 8de071a..200a74f 100644
--- a/sandbox/plc4c/spi/src/main/c/plc4c_private_types.c
+++ b/sandbox/plc4c/spi/src/main/c/plc4c_connection.c
@@ -17,24 +17,14 @@
  * under the License.
  */
 
-#include "plc4c.h"
+#include "plc4c_connection.h"
+#include "plc4c_types.h"
 
-/* private!! */
+error_code plc4c_connection_disconnect(plc4c_connection *connection) {
+    return OK;
+}
 
-struct plc4c_system_t {
-   /* drivers */
+char* plc4c_connection_get_connection_string(plc4c_connection *connection) {
+    return connection->connection_string;
+}
 
-   /* connections */
-
-   /* callbacks */
-};
-
-struct plc4c_driver_t {
-  /* name */
-
-  /* ??? */
-};
-
-struct plc4c_connection_t {
- /* ???? */
-};
\ No newline at end of file
diff --git a/sandbox/plc4c/spi/src/main/c/plc4c.c b/sandbox/plc4c/spi/src/main/c/plc4c_system.c
similarity index 58%
rename from sandbox/plc4c/spi/src/main/c/plc4c.c
rename to sandbox/plc4c/spi/src/main/c/plc4c_system.c
index 34cfe13..988f121 100644
--- a/sandbox/plc4c/spi/src/main/c/plc4c.c
+++ b/sandbox/plc4c/spi/src/main/c/plc4c_system.c
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-#include "plc4c.h"
+#include "plc4c_system.h"
 
 error_code plc4c_system_create(plc4c_system **system) {
     return OK;
@@ -28,41 +28,41 @@ void plc4c_system_destroy(plc4c_system *system) {
 }
 
 void plc4c_system_set_on_driver_loaded(plc4c_system *system,
-        plc4c_system_callback_on_driver_loaded callback) {
+                                       plc4c_system_callback_on_driver_loaded callback) {
 
 }
 
 void plc4c_system_set_on_driver_load_error(plc4c_system *system,
-        plc4c_system_callback_driver_load_error callback) {
+                                           plc4c_system_callback_driver_load_error callback) {
 
 }
 
 void plc4c_system_set_on_connection(plc4c_system *system,
-        plc4c_system_callback_on_connection callback) {
+                                    plc4c_system_callback_on_connection callback) {
 
 }
 
 void plc4c_system_set_on_connection_error(plc4c_system *system,
-        plc4c_system_callback_connection_error callback) {
+                                          plc4c_system_callback_connection_error callback) {
 
 }
 
 void plc4c_system_set_on_disconnection(plc4c_system *system,
-        plc4c_system_callback_on_disconnection callback) {
+                                       plc4c_system_callback_on_disconnection callback) {
 
 }
 
 void plc4c_system_set_on_disconnection_error(plc4c_system *system,
-        plc4c_system_callback_disconnection_error callback) {
+                                             plc4c_system_callback_disconnection_error callback) {
 
 }
 
 void plc4c_system_set_on_loop_error(plc4c_system *system,
-        plc4c_system_callback_loop_error callback) {
+                                    plc4c_system_callback_loop_error callback) {
 
 }
 
-error_code plc4c_init(plc4c_system *system) {
+error_code plc4c_system_init(plc4c_system *system) {
     return OK;
 }
 
@@ -76,25 +76,8 @@ error_code plc4c_system_connect(plc4c_system *system,
     return OK;
 }
 
-error_code plc4c_system_connect_callback(plc4c_system *system,
-                                         const char *connectionString,
-                                         plc4c_connection **connection,
-                                         plc4c_system_callback_on_connection success_callback,
-                                         plc4c_system_callback_connection_error error_callback) {
-    return OK;
-}
-
-error_code plc4c_disconnect(plc4c_connection *connection) {
-    return OK;
-}
-
-error_code plc4c_disconnect_callback(plc4c_connection *connection,
-                                     plc4c_system_callback_on_disconnection success_callback,
-                                     plc4c_system_callback_disconnection_error error_callback) {
-    return OK;
-}
-
 error_code plc4c_system_loop() {
     return OK;
 }
 
+
diff --git a/sandbox/plc4c/spi/src/main/c/plc4c_private_types.c b/sandbox/plc4c/spi/src/main/c/plc4c_types.c
similarity index 94%
rename from sandbox/plc4c/spi/src/main/c/plc4c_private_types.c
rename to sandbox/plc4c/spi/src/main/c/plc4c_types.c
index 8de071a..7e79d44 100644
--- a/sandbox/plc4c/spi/src/main/c/plc4c_private_types.c
+++ b/sandbox/plc4c/spi/src/main/c/plc4c_types.c
@@ -17,9 +17,7 @@
  * under the License.
  */
 
-#include "plc4c.h"
-
-/* private!! */
+#include "plc4c_types.h"
 
 struct plc4c_system_t {
    /* drivers */
@@ -36,5 +34,7 @@ struct plc4c_driver_t {
 };
 
 struct plc4c_connection_t {
+    char* connection_string;
  /* ???? */
-};
\ No newline at end of file
+};
+