P_LIB_API void p_hash_table_insert (PHashTable *table, ppointer key, ppointer value) { PHashTableNode *node; puint hash; if (P_UNLIKELY (table == NULL)) return; if ((node = pp_hash_table_find_node (table, key)) == NULL) { if (P_UNLIKELY ((node = p_malloc0 (sizeof (PHashTableNode))) == NULL)) { P_ERROR ("PHashTable::p_hash_table_insert: failed to allocate memory"); return; } hash = pp_hash_table_calc_hash (key, table->size); /* Insert a new node in front of others */ node->key = key; node->value = value; node->next = table->table[hash]; table->table[hash] = node; } else node->value = value; }
P_LIB_API pchar * p_strtok (pchar *str, const pchar *delim, pchar **buf) { if (P_UNLIKELY (delim == NULL)) return str; #ifdef P_OS_WIN # ifdef P_CC_MSVC if (P_UNLIKELY (buf == NULL)) return str; # if _MSC_VER < 1400 P_UNUSED (buf); return strtok (str, delim); # else return strtok_s (str, delim, buf); # endif # else P_UNUSED (buf); return strtok (str, delim); # endif #else if (P_UNLIKELY (buf == NULL)) return str; return strtok_r (str, delim, buf); #endif }
P_LIB_API void p_shm_buffer_clear (PShmBuffer *buf) { ppointer addr; psize size; if (P_UNLIKELY (buf == NULL)) return; if (P_UNLIKELY ((addr = p_shm_get_address (buf->shm)) == NULL)) { P_ERROR ("PShmBuffer::p_shm_buffer_clear: p_shm_get_address() failed"); return; } size = p_shm_get_size (buf->shm); if (P_UNLIKELY (p_shm_lock (buf->shm, NULL) == FALSE)) { P_ERROR ("PShmBuffer::p_shm_buffer_clear: p_shm_lock() failed"); return; } memset (addr, 0, size); if (P_UNLIKELY (p_shm_unlock (buf->shm, NULL) == FALSE)) P_ERROR ("PShmBuffer::p_shm_buffer_clear: p_shm_unlock() failed"); }
P_LIB_API pboolean p_dir_create (const pchar *path, pint mode, PError **error) { P_UNUSED (mode); if (P_UNLIKELY (path == NULL)) { p_error_set_error_p (error, (pint) P_ERROR_IO_INVALID_ARGUMENT, 0, "Invalid input argument"); return FALSE; } if (p_dir_is_exists (path)) return TRUE; if (P_UNLIKELY (CreateDirectoryA (path, NULL) == 0)) { p_error_set_error_p (error, (pint) p_error_get_last_io (), p_error_get_last_system (), "Failed to call CreateDirectoryA() to create directory"); return FALSE; } else return TRUE; }
P_LIB_API pboolean p_dir_remove (const pchar *path, PError **error) { if (P_UNLIKELY (path == NULL)) { p_error_set_error_p (error, (pint) P_ERROR_IO_INVALID_ARGUMENT, 0, "Invalid input argument"); return FALSE; } if (!p_dir_is_exists (path)) { p_error_set_error_p (error, (pint) P_ERROR_IO_NOT_EXISTS, 0, "Specified directory doesn't exist"); return FALSE; } if (P_UNLIKELY (RemoveDirectoryA (path) == 0)) { p_error_set_error_p (error, (pint) p_error_get_last_io (), p_error_get_last_system (), "Failed to call RemoveDirectoryA() to remove directory"); return FALSE; } else return TRUE; }
P_LIB_API PDirEntry * p_dir_get_next_entry (PDir *dir, PError **error) { PDirEntry *ret; DWORD dwAttrs; if (P_UNLIKELY (dir == NULL)) { p_error_set_error_p (error, (pint) P_ERROR_IO_INVALID_ARGUMENT, 0, "Invalid input argument"); return NULL; } if (dir->cached == TRUE) dir->cached = FALSE; else { if (P_UNLIKELY (dir->search_handle == INVALID_HANDLE_VALUE)) { p_error_set_error_p (error, (pint) P_ERROR_IO_INVALID_ARGUMENT, 0, "Not a valid (or closed) directory stream"); return NULL; } if (P_UNLIKELY (!FindNextFileA (dir->search_handle, &dir->find_data))) { p_error_set_error_p (error, (pint) p_error_get_last_io (), p_error_get_last_system (), "Failed to call FindNextFileA() to read directory stream"); FindClose (dir->search_handle); dir->search_handle = INVALID_HANDLE_VALUE; return NULL; } } if (P_UNLIKELY ((ret = p_malloc0 (sizeof (PDirEntry))) == NULL)) { p_error_set_error_p (error, (pint) P_ERROR_IO_NO_RESOURCES, 0, "Failed to allocate memory for directory entry"); return NULL; } ret->name = p_strdup (dir->find_data.cFileName); dwAttrs = dir->find_data.dwFileAttributes; if (dwAttrs & FILE_ATTRIBUTE_DIRECTORY) ret->type = P_DIR_ENTRY_TYPE_DIR; else if (dwAttrs & FILE_ATTRIBUTE_DEVICE) ret->type = P_DIR_ENTRY_TYPE_OTHER; else ret->type = P_DIR_ENTRY_TYPE_FILE; return ret; }
P_LIB_API PDir * p_dir_new (const pchar *path, PError **error) { PDir *ret; pchar *pathp; if (P_UNLIKELY (path == NULL)) { p_error_set_error_p (error, (pint) P_ERROR_IO_INVALID_ARGUMENT, 0, "Invalid input argument"); return NULL; } if (P_UNLIKELY ((ret = p_malloc0 (sizeof (PDir))) == NULL)) { p_error_set_error_p (error, (pint) P_ERROR_IO_NO_RESOURCES, 0, "Failed to allocate memory for directory structure"); return NULL; } if (P_UNLIKELY (!GetFullPathNameA (path, MAX_PATH, ret->path, NULL))) { p_error_set_error_p (error, (pint) p_error_get_last_io (), p_error_get_last_system (), "Failed to call GetFullPathNameA() to get directory path"); p_free (ret); return NULL; } /* Append the search pattern "\\*\0" to the directory name */ pathp = strchr (ret->path, '\0'); if (ret->path < pathp && *(pathp - 1) != '\\' && *(pathp - 1) != ':') *pathp++ = '\\'; *pathp++ = '*'; *pathp = '\0'; /* Open directory stream and retrieve the first entry */ ret->search_handle = FindFirstFileA (ret->path, &ret->find_data); if (P_UNLIKELY (ret->search_handle == INVALID_HANDLE_VALUE)) { p_error_set_error_p (error, (pint) p_error_get_last_io (), p_error_get_last_system (), "Failed to call FindFirstFileA() to open directory stream"); p_free (ret); return NULL; } ret->cached = TRUE; ret->orig_path = p_strdup (path); return ret; }
P_LIB_API pint p_shm_buffer_read (PShmBuffer *buf, ppointer storage, psize len, PError **error) { psize read_pos, write_pos; psize data_aval, to_copy; puint i; ppointer addr; if (P_UNLIKELY (buf == NULL || storage == NULL || len == 0)) { p_error_set_error_p (error, (pint) P_ERROR_IPC_INVALID_ARGUMENT, 0, "Invalid input argument"); return -1; } if (P_UNLIKELY ((addr = p_shm_get_address (buf->shm)) == NULL)) { p_error_set_error_p (error, (pint) P_ERROR_IPC_INVALID_ARGUMENT, 0, "Unable to get shared memory address"); return -1; } if (P_UNLIKELY (p_shm_lock (buf->shm, error) == FALSE)) return -1; memcpy (&read_pos, (pchar *) addr + P_SHM_BUFFER_READ_OFFSET, sizeof (read_pos)); memcpy (&write_pos, (pchar *) addr + P_SHM_BUFFER_WRITE_OFFSET, sizeof (write_pos)); if (read_pos == write_pos) { if (P_UNLIKELY (p_shm_unlock (buf->shm, error) == FALSE)) return -1; return 0; } data_aval = pp_shm_buffer_get_used_space (buf); to_copy = (data_aval <= len) ? data_aval : len; for (i = 0; i < to_copy; ++i) memcpy ((pchar *) storage + i, (pchar *) addr + P_SHM_BUFFER_DATA_OFFSET + ((read_pos + i) % buf->size), 1); read_pos = (read_pos + to_copy) % buf->size; memcpy ((pchar *) addr + P_SHM_BUFFER_READ_OFFSET, &read_pos, sizeof (read_pos)); if (P_UNLIKELY (p_shm_unlock (buf->shm, error) == FALSE)) return -1; return (pint) to_copy; }
P_LIB_API void p_mutex_free (PMutex *mutex) { if (P_UNLIKELY (mutex == NULL)) return; if (P_UNLIKELY (mutex_destroy (&mutex->hdl) != 0)) P_ERROR ("PMutex::p_mutex_unlock: mutex_destroy() failed"); p_free (mutex); }
P_LIB_API void p_rwlock_free (PRWLock *lock) { if (P_UNLIKELY (lock == NULL)) return; if (P_UNLIKELY (rwlock_destroy (&lock->hdl) != 0)) P_ERROR ("PRWLock::p_rwlock_free: rwlock_destroy() failed"); p_free (lock); }
P_LIB_API PShm * p_shm_new (const pchar *name, psize size, PShmAccessPerms perms, PError **error) { PShm *ret; pchar *new_name; if (P_UNLIKELY (name == NULL)) { p_error_set_error_p (error, (pint) P_ERROR_IPC_INVALID_ARGUMENT, 0, "Invalid input argument"); return NULL; } if (P_UNLIKELY ((ret = p_malloc0 (sizeof (PShm))) == NULL)) { p_error_set_error_p (error, (pint) P_ERROR_IPC_NO_RESOURCES, 0, "Failed to allocate memory for shared segment"); return NULL; } if (P_UNLIKELY ((new_name = p_malloc0 (strlen (name) + strlen (P_SHM_SUFFIX) + 1)) == NULL)) { p_error_set_error_p (error, (pint) P_ERROR_IPC_NO_RESOURCES, 0, "Failed to allocate memory for segment name"); p_shm_free (ret); return NULL; } strcpy (new_name, name); strcat (new_name, P_SHM_SUFFIX); ret->platform_key = p_ipc_get_platform_key (new_name, FALSE); ret->perms = perms; ret->size = size; p_free (new_name); if (P_UNLIKELY (pp_shm_create_handle (ret, error) == FALSE)) { p_shm_free (ret); return NULL; } if (P_LIKELY (ret->size > size && size != 0)) ret->size = size; return ret; }
P_LIB_API pssize p_shm_buffer_write (PShmBuffer *buf, ppointer data, psize len, PError **error) { psize read_pos, write_pos; puint i; ppointer addr; if (P_UNLIKELY (buf == NULL || data == NULL || len == 0)) { p_error_set_error_p (error, (pint) P_ERROR_IPC_INVALID_ARGUMENT, 0, "Invalid input argument"); return -1; } if (P_UNLIKELY ((addr = p_shm_get_address (buf->shm)) == NULL)) { p_error_set_error_p (error, (pint) P_ERROR_IPC_INVALID_ARGUMENT, 0, "Unable to get shared memory address"); return -1; } if (P_UNLIKELY (p_shm_lock (buf->shm, error) == FALSE)) return -1; memcpy (&read_pos, (pchar *) addr + P_SHM_BUFFER_READ_OFFSET, sizeof (read_pos)); memcpy (&write_pos, (pchar *) addr + P_SHM_BUFFER_WRITE_OFFSET, sizeof (write_pos)); if (pp_shm_buffer_get_free_space (buf) < len) { if (P_UNLIKELY (p_shm_unlock (buf->shm, error) == FALSE)) return -1; return 0; } for (i = 0; i < len; ++i) memcpy ((pchar *) addr + P_SHM_BUFFER_DATA_OFFSET + ((write_pos + i) % buf->size), (pchar *) data + i, 1); write_pos = (write_pos + len) % buf->size; memcpy ((pchar *) addr + P_SHM_BUFFER_WRITE_OFFSET, &write_pos, sizeof (write_pos)); if (P_UNLIKELY (p_shm_unlock (buf->shm, error) == FALSE)) return -1; return (pssize) len; }
P_LIB_API pboolean p_rwlock_writer_lock (PRWLock *lock) { if (P_UNLIKELY (lock == NULL)) return FALSE; if (P_UNLIKELY (rw_wrlock (&lock->hdl) == 0)) return TRUE; else { P_ERROR ("PRWLock::p_rwlock_writer_lock: rw_wrlock() failed"); return FALSE; } }
P_LIB_API void p_dir_free (PDir *dir) { if (P_UNLIKELY (dir == NULL)) return; if (P_LIKELY (dir->dir != NULL)) { if (P_UNLIKELY (closedir (dir->dir) != 0)) P_ERROR ("PDir::p_dir_free: closedir() failed"); } p_free (dir->path); p_free (dir->orig_path); p_free (dir); }
P_LIB_API PError * p_error_copy (PError *error) { PError *ret; if (P_UNLIKELY (error == NULL)) return NULL; if (P_UNLIKELY ((ret = p_error_new_literal (error->code, error->native_code, error->message)) == NULL)) return NULL; return ret; }
P_LIB_API void p_hash_table_remove (PHashTable *table, pconstpointer key) { PHashTableNode *node, *prev_node; puint hash; if (P_UNLIKELY (table == NULL)) return; if (pp_hash_table_find_node (table, key) != NULL) { hash = pp_hash_table_calc_hash (key, table->size); node = table->table[hash]; prev_node = NULL; while (node != NULL) { if (node->key == key) { if (prev_node == NULL) table->table[hash] = node->next; else prev_node->next = node->next; p_free (node); break; } else { prev_node = node; node = node->next; } } } }
P_LIB_API void p_time_profiler_reset (PTimeProfiler *profiler) { if (P_UNLIKELY (profiler == NULL)) return; profiler->counter = p_time_profiler_get_ticks_internal (); }
P_LIB_API pint p_error_get_native_code (PError *error) { if (P_UNLIKELY (error == NULL)) return 0; return error->native_code; }
P_LIB_API pboolean p_mutex_trylock (PMutex *mutex) { if (P_UNLIKELY (mutex == NULL)) return FALSE; return (mutex_trylock (&mutex->hdl) == 0) ? TRUE : FALSE; }
P_LIB_API pchar * p_dir_get_path (const PDir *dir) { if (P_UNLIKELY (dir == NULL)) return NULL; return p_strdup (dir->orig_path); }
P_LIB_API pboolean p_spinlock_unlock (PSpinLock *spinlock) { if (P_UNLIKELY (spinlock == NULL)) return FALSE; return p_mutex_unlock (spinlock->mutex); }
P_LIB_API pboolean p_cond_variable_broadcast (PCondVariable *cond) { if (P_UNLIKELY (cond == NULL)) return FALSE; return pp_cond_variable_brdcast_func (cond); }
P_LIB_API pboolean p_cond_variable_signal (PCondVariable *cond) { if (P_UNLIKELY (cond == NULL)) return FALSE; return pp_cond_variable_signal_func (cond); }
P_LIB_API void p_shm_buffer_take_ownership (PShmBuffer *buf) { if (P_UNLIKELY (buf == NULL)) return; p_shm_take_ownership (buf->shm); }
P_LIB_API puint64 p_time_profiler_elapsed_usecs (const PTimeProfiler *profiler) { if (P_UNLIKELY (profiler == NULL)) return 0; return p_time_profiler_elapsed_usecs_internal (profiler); }
P_LIB_API const pchar * p_error_get_message (PError *error) { if (P_UNLIKELY (error == NULL)) return NULL; return error->message; }
P_LIB_API ppointer p_shm_get_address (const PShm *shm) { if (P_UNLIKELY (shm == NULL)) return NULL; return shm->addr; }
P_LIB_API pboolean p_rwlock_reader_trylock (PRWLock *lock) { if (P_UNLIKELY (lock == NULL)) return FALSE; return (rw_tryrdlock (&lock->hdl) == 0) ? TRUE : FALSE; }
P_LIB_API psize p_shm_get_size (const PShm *shm) { if (P_UNLIKELY (shm == NULL)) return 0; return shm->size; }
P_LIB_API PFuncAddr p_library_loader_get_symbol (PLibraryLoader *loader, const pchar *sym) { if (P_UNLIKELY (loader == NULL || sym == NULL || loader->handle == NULL)) return NULL; return (PFuncAddr) dlsym (loader->handle, sym); }