static URI_INLINE int URI_FUNC()

in cpp/src/arrow/vendored/uriparser/UriRecompose.c [91:573]


static URI_INLINE int URI_FUNC(ToStringEngine)(URI_CHAR * dest,
		const URI_TYPE(Uri) * uri, int maxChars, int * charsWritten,
		int * charsRequired) {
	int written = 0;
	if ((uri == NULL) || ((dest == NULL) && (charsRequired == NULL))) {
		if (charsWritten != NULL) {
			*charsWritten = 0;
		}
		return URI_ERROR_NULL;
	}

	if (maxChars < 1) {
		if (charsWritten != NULL) {
			*charsWritten = 0;
		}
		return URI_ERROR_TOSTRING_TOO_LONG;
	}
	maxChars--; /* So we don't have to subtract 1 for '\0' all the time */

	/* [01/19]	result = "" */
				if (dest != NULL) {
					dest[0] = _UT('\0');
				} else {
					(*charsRequired) = 0;
				}
	/* [02/19]	if defined(scheme) then */
				if (uri->scheme.first != NULL) {
	/* [03/19]		append scheme to result; */
					const int charsToWrite
							= (int)(uri->scheme.afterLast - uri->scheme.first);
					if (dest != NULL) {
						if (written + charsToWrite <= maxChars) {
							memcpy(dest + written, uri->scheme.first,
									charsToWrite * sizeof(URI_CHAR));
							written += charsToWrite;
						} else {
							dest[0] = _UT('\0');
							if (charsWritten != NULL) {
								*charsWritten = 0;
							}
							return URI_ERROR_TOSTRING_TOO_LONG;
						}
					} else {
						(*charsRequired) += charsToWrite;
					}
	/* [04/19]		append ":" to result; */
					if (dest != NULL) {
						if (written + 1 <= maxChars) {
							memcpy(dest + written, _UT(":"),
									1 * sizeof(URI_CHAR));
							written += 1;
						} else {
							dest[0] = _UT('\0');
							if (charsWritten != NULL) {
								*charsWritten = 0;
							}
							return URI_ERROR_TOSTRING_TOO_LONG;
						}
					} else {
						(*charsRequired) += 1;
					}
	/* [05/19]	endif; */
				}
	/* [06/19]	if defined(authority) then */
				if (URI_FUNC(IsHostSet)(uri)) {
	/* [07/19]		append "//" to result; */
					if (dest != NULL) {
						if (written + 2 <= maxChars) {
							memcpy(dest + written, _UT("//"),
									2 * sizeof(URI_CHAR));
							written += 2;
						} else {
							dest[0] = _UT('\0');
							if (charsWritten != NULL) {
								*charsWritten = 0;
							}
							return URI_ERROR_TOSTRING_TOO_LONG;
						}
					} else {
						(*charsRequired) += 2;
					}
	/* [08/19]		append authority to result; */
					/* UserInfo */
					if (uri->userInfo.first != NULL) {
						const int charsToWrite = (int)(uri->userInfo.afterLast - uri->userInfo.first);
						if (dest != NULL) {
							if (written + charsToWrite <= maxChars) {
								memcpy(dest + written, uri->userInfo.first,
										charsToWrite * sizeof(URI_CHAR));
								written += charsToWrite;
							} else {
								dest[0] = _UT('\0');
								if (charsWritten != NULL) {
									*charsWritten = 0;
								}
								return URI_ERROR_TOSTRING_TOO_LONG;
							}

							if (written + 1 <= maxChars) {
								memcpy(dest + written, _UT("@"),
										1 * sizeof(URI_CHAR));
								written += 1;
							} else {
								dest[0] = _UT('\0');
								if (charsWritten != NULL) {
									*charsWritten = 0;
								}
								return URI_ERROR_TOSTRING_TOO_LONG;
							}
						} else {
							(*charsRequired) += charsToWrite + 1;
						}
					}

					/* Host */
					if (uri->hostData.ip4 != NULL) {
						/* IPv4 */
						int i = 0;
						for (; i < 4; i++) {
							const unsigned char value = uri->hostData.ip4->data[i];
							const int charsToWrite = (value > 99) ? 3 : ((value > 9) ? 2 : 1);
							if (dest != NULL) {
								if (written + charsToWrite <= maxChars) {
									URI_CHAR text[4];
									if (value > 99) {
										text[0] = _UT('0') + (value / 100);
										text[1] = _UT('0') + ((value % 100) / 10);
										text[2] = _UT('0') + (value % 10);
									} else if (value > 9)  {
										text[0] = _UT('0') + (value / 10);
										text[1] = _UT('0') + (value % 10);
									} else {
										text[0] = _UT('0') + value;
									}
									text[charsToWrite] = _UT('\0');
									memcpy(dest + written, text, charsToWrite * sizeof(URI_CHAR));
									written += charsToWrite;
								} else {
									dest[0] = _UT('\0');
									if (charsWritten != NULL) {
										*charsWritten = 0;
									}
									return URI_ERROR_TOSTRING_TOO_LONG;
								}
								if (i < 3) {
									if (written + 1 <= maxChars) {
										memcpy(dest + written, _UT("."),
												1 * sizeof(URI_CHAR));
										written += 1;
									} else {
										dest[0] = _UT('\0');
										if (charsWritten != NULL) {
											*charsWritten = 0;
										}
										return URI_ERROR_TOSTRING_TOO_LONG;
									}
								}
							} else {
								(*charsRequired) += charsToWrite + ((i == 3) ? 0 : 1);
							}
						}
					} else if (uri->hostData.ip6 != NULL) {
						/* IPv6 */
						int i = 0;
						if (dest != NULL) {
							if (written + 1 <= maxChars) {
								memcpy(dest + written, _UT("["),
										1 * sizeof(URI_CHAR));
								written += 1;
							} else {
								dest[0] = _UT('\0');
								if (charsWritten != NULL) {
									*charsWritten = 0;
								}
								return URI_ERROR_TOSTRING_TOO_LONG;
							}
						} else {
							(*charsRequired) += 1;
						}

						for (; i < 16; i++) {
							const unsigned char value = uri->hostData.ip6->data[i];
							if (dest != NULL) {
								if (written + 2 <= maxChars) {
									URI_CHAR text[3];
									text[0] = URI_FUNC(HexToLetterEx)(value / 16, URI_FALSE);
									text[1] = URI_FUNC(HexToLetterEx)(value % 16, URI_FALSE);
									text[2] = _UT('\0');
									memcpy(dest + written, text, 2 * sizeof(URI_CHAR));
									written += 2;
								} else {
									dest[0] = _UT('\0');
									if (charsWritten != NULL) {
										*charsWritten = 0;
									}
									return URI_ERROR_TOSTRING_TOO_LONG;
								}
							} else {
								(*charsRequired) += 2;
							}
							if (((i & 1) == 1) && (i < 15)) {
								if (dest != NULL) {
									if (written + 1 <= maxChars) {
										memcpy(dest + written, _UT(":"),
												1 * sizeof(URI_CHAR));
										written += 1;
									} else {
										dest[0] = _UT('\0');
										if (charsWritten != NULL) {
											*charsWritten = 0;
										}
										return URI_ERROR_TOSTRING_TOO_LONG;
									}
								} else {
									(*charsRequired) += 1;
								}
							}
						}

						if (dest != NULL) {
							if (written + 1 <= maxChars) {
								memcpy(dest + written, _UT("]"),
										1 * sizeof(URI_CHAR));
								written += 1;
							} else {
								dest[0] = _UT('\0');
								if (charsWritten != NULL) {
									*charsWritten = 0;
								}
								return URI_ERROR_TOSTRING_TOO_LONG;
							}
						} else {
							(*charsRequired) += 1;
						}
					} else if (uri->hostData.ipFuture.first != NULL) {
						/* IPvFuture */
						const int charsToWrite = (int)(uri->hostData.ipFuture.afterLast
								- uri->hostData.ipFuture.first);
						if (dest != NULL) {
							if (written + 1 <= maxChars) {
								memcpy(dest + written, _UT("["),
										1 * sizeof(URI_CHAR));
								written += 1;
							} else {
								dest[0] = _UT('\0');
								if (charsWritten != NULL) {
									*charsWritten = 0;
								}
								return URI_ERROR_TOSTRING_TOO_LONG;
							}

							if (written + charsToWrite <= maxChars) {
								memcpy(dest + written, uri->hostData.ipFuture.first, charsToWrite * sizeof(URI_CHAR));
								written += charsToWrite;
							} else {
								dest[0] = _UT('\0');
								if (charsWritten != NULL) {
									*charsWritten = 0;
								}
								return URI_ERROR_TOSTRING_TOO_LONG;
							}

							if (written + 1 <= maxChars) {
								memcpy(dest + written, _UT("]"),
										1 * sizeof(URI_CHAR));
								written += 1;
							} else {
								dest[0] = _UT('\0');
								if (charsWritten != NULL) {
									*charsWritten = 0;
								}
								return URI_ERROR_TOSTRING_TOO_LONG;
							}
						} else {
							(*charsRequired) += 1 + charsToWrite + 1;
						}
					} else if (uri->hostText.first != NULL) {
						/* Regname */
						const int charsToWrite = (int)(uri->hostText.afterLast - uri->hostText.first);
						if (dest != NULL) {
							if (written + charsToWrite <= maxChars) {
								memcpy(dest + written, uri->hostText.first,
										charsToWrite * sizeof(URI_CHAR));
								written += charsToWrite;
							} else {
								dest[0] = _UT('\0');
								if (charsWritten != NULL) {
									*charsWritten = 0;
								}
								return URI_ERROR_TOSTRING_TOO_LONG;
							}
						} else {
							(*charsRequired) += charsToWrite;
						}
					}

					/* Port */
					if (uri->portText.first != NULL) {
						const int charsToWrite = (int)(uri->portText.afterLast - uri->portText.first);
						if (dest != NULL) {
							/* Leading ':' */
							if (written + 1 <= maxChars) {
									memcpy(dest + written, _UT(":"),
											1 * sizeof(URI_CHAR));
									written += 1;
							} else {
								dest[0] = _UT('\0');
								if (charsWritten != NULL) {
									*charsWritten = 0;
								}
								return URI_ERROR_TOSTRING_TOO_LONG;
							}

							/* Port number */
							if (written + charsToWrite <= maxChars) {
								memcpy(dest + written, uri->portText.first,
										charsToWrite * sizeof(URI_CHAR));
								written += charsToWrite;
							} else {
								dest[0] = _UT('\0');
								if (charsWritten != NULL) {
									*charsWritten = 0;
								}
								return URI_ERROR_TOSTRING_TOO_LONG;
							}
						} else {
							(*charsRequired) += 1 + charsToWrite;
						}
					}
	/* [09/19]	endif; */
				}
	/* [10/19]	append path to result; */
				/* Slash needed here? */
				if (uri->absolutePath || ((uri->pathHead != NULL)
						&& URI_FUNC(IsHostSet)(uri))) {
					if (dest != NULL) {
						if (written + 1 <= maxChars) {
							memcpy(dest + written, _UT("/"),
									1 * sizeof(URI_CHAR));
							written += 1;
						} else {
							dest[0] = _UT('\0');
							if (charsWritten != NULL) {
								*charsWritten = 0;
							}
							return URI_ERROR_TOSTRING_TOO_LONG;
						}
					} else {
						(*charsRequired) += 1;
					}
				}

				if (uri->pathHead != NULL) {
					URI_TYPE(PathSegment) * walker = uri->pathHead;
					do {
						const int charsToWrite = (int)(walker->text.afterLast - walker->text.first);
						if (dest != NULL) {
							if (written + charsToWrite <= maxChars) {
								memcpy(dest + written, walker->text.first,
										charsToWrite * sizeof(URI_CHAR));
								written += charsToWrite;
							} else {
								dest[0] = _UT('\0');
								if (charsWritten != NULL) {
									*charsWritten = 0;
								}
								return URI_ERROR_TOSTRING_TOO_LONG;
							}
						} else {
							(*charsRequired) += charsToWrite;
						}

						/* Not last segment -> append slash */
						if (walker->next != NULL) {
							if (dest != NULL) {
								if (written + 1 <= maxChars) {
									memcpy(dest + written, _UT("/"),
											1 * sizeof(URI_CHAR));
									written += 1;
								} else {
									dest[0] = _UT('\0');
									if (charsWritten != NULL) {
										*charsWritten = 0;
									}
									return URI_ERROR_TOSTRING_TOO_LONG;
								}
							} else {
								(*charsRequired) += 1;
							}
						}

						walker = walker->next;
					} while (walker != NULL);
				}
	/* [11/19]	if defined(query) then */
				if (uri->query.first != NULL) {
	/* [12/19]		append "?" to result; */
					if (dest != NULL) {
						if (written + 1 <= maxChars) {
							memcpy(dest + written, _UT("?"),
									1 * sizeof(URI_CHAR));
							written += 1;
						} else {
							dest[0] = _UT('\0');
							if (charsWritten != NULL) {
								*charsWritten = 0;
							}
							return URI_ERROR_TOSTRING_TOO_LONG;
						}
					} else {
						(*charsRequired) += 1;
					}
	/* [13/19]		append query to result; */
					{
						const int charsToWrite
								= (int)(uri->query.afterLast - uri->query.first);
						if (dest != NULL) {
							if (written + charsToWrite <= maxChars) {
								memcpy(dest + written, uri->query.first,
										charsToWrite * sizeof(URI_CHAR));
								written += charsToWrite;
							} else {
								dest[0] = _UT('\0');
								if (charsWritten != NULL) {
									*charsWritten = 0;
								}
								return URI_ERROR_TOSTRING_TOO_LONG;
							}
						} else {
							(*charsRequired) += charsToWrite;
						}
					}
	/* [14/19]	endif; */
				}
	/* [15/19]	if defined(fragment) then */
				if (uri->fragment.first != NULL) {
	/* [16/19]		append "#" to result; */
					if (dest != NULL) {
						if (written + 1 <= maxChars) {
							memcpy(dest + written, _UT("#"),
									1 * sizeof(URI_CHAR));
							written += 1;
						} else {
							dest[0] = _UT('\0');
							if (charsWritten != NULL) {
								*charsWritten = 0;
							}
							return URI_ERROR_TOSTRING_TOO_LONG;
						}
					} else {
						(*charsRequired) += 1;
					}
	/* [17/19]		append fragment to result; */
					{
						const int charsToWrite
								= (int)(uri->fragment.afterLast - uri->fragment.first);
						if (dest != NULL) {
							if (written + charsToWrite <= maxChars) {
								memcpy(dest + written, uri->fragment.first,
										charsToWrite * sizeof(URI_CHAR));
								written += charsToWrite;
							} else {
								dest[0] = _UT('\0');
								if (charsWritten != NULL) {
									*charsWritten = 0;
								}
								return URI_ERROR_TOSTRING_TOO_LONG;
							}
						} else {
							(*charsRequired) += charsToWrite;
						}
					}
	/* [18/19]	endif; */
				}
	/* [19/19]	return result; */
				if (dest != NULL) {
					dest[written++] = _UT('\0');
					if (charsWritten != NULL) {
						*charsWritten = written;
					}
				}
				return URI_SUCCESS;
}