src/table.c
void
update_order_map(ScrDesc *scrdesc, DataDesc *desc, int sbcn, bool desc_sort)
{
	LineBuffer	   *lnb = &desc->rows;
	char		   *nullstr = NULL;
	int				xmin, xmax;
	int				lineno = 0;
	bool			continual_line = false;
	bool			isnull;
	bool			detect_string_column = false;
	bool			border0 = (desc->border_type == 0);
	SortData	   *sortbuf;
	int				sortbuf_pos = 0;
	int			i;

	xmin = desc->cranges[sbcn - 1].xmin;
	xmax = desc->cranges[sbcn - 1].xmax;

	sortbuf = smalloc(desc->total_rows * sizeof(SortData));

	/* multilines should be detected first */
	multilines_detection(desc);

	lnb = &desc->rows;
	lineno = 0;
	sortbuf_pos = 0;

	if (!desc->order_map)
	{
		desc->order_map = smalloc(desc->total_rows * sizeof(MappedLine));
		desc->order_map_items = desc->total_rows;
	}

	/*
	 * There are two possible sorting methods: numeric or string.
	 * We can try numeric sort first if all values are numbers or
	 * just only one type of string value (like NULL string). This
	 * value can be repeated,
	 *
	 * When there are more different strings, then start again and
	 * use string sort.
	 */
	while (lnb)
	{
		for (i = 0; i < lnb->nrows; i++)
		{
			desc->order_map[lineno].lnb = lnb;
			desc->order_map[lineno].lnb_row = i;

			if (lineno >= desc->first_data_row && lineno <= desc->last_data_row)
			{
				if (!continual_line)
				{
					sortbuf[sortbuf_pos].lnb = lnb;
					sortbuf[sortbuf_pos].lnb_row = i;
					sortbuf[sortbuf_pos].strxfrm = NULL;

					if (cut_numeric_value(lnb->rows[i],
										   xmin, xmax,
										   &sortbuf[sortbuf_pos].d,
										   border0,
										   &isnull,
										   &nullstr))
						sortbuf[sortbuf_pos++].info = INFO_DOUBLE;
					else
					{
						sortbuf[sortbuf_pos++].info = INFO_UNKNOWN;
						if (!isnull)
						{
							detect_string_column = true;
							goto sort_by_string;
						}
					}
				}

				if (desc->has_multilines)
				{
					continual_line = (lnb->lineinfo &&
									  (lnb->lineinfo[i].mask & LINEINFO_CONTINUATION));
				}
			}

			lineno += 1;
		}

		lnb = lnb->next;
	}

sort_by_string:

	free(nullstr);

	if (detect_string_column)
	{
		/* read data again and use nls_string */
		lnb = &desc->rows;
		lineno = 0;
		sortbuf_pos = 0;
		while (lnb)
		{
			for (i = 0; i < lnb->nrows; i++)
			{
				desc->order_map[lineno].lnb = lnb;
				desc->order_map[lineno].lnb_row = i;

				if (lineno >= desc->first_data_row && lineno <= desc->last_data_row)
				{
					if (!continual_line)
					{
						sortbuf[sortbuf_pos].lnb = lnb;
						sortbuf[sortbuf_pos].lnb_row = i;
						sortbuf[sortbuf_pos].d = 0.0;

						if (cut_text(lnb->rows[i], xmin, xmax, border0, &sortbuf[sortbuf_pos].strxfrm))
							sortbuf[sortbuf_pos++].info = INFO_STRXFRM;
						else
							sortbuf[sortbuf_pos++].info = INFO_UNKNOWN;		/* empty string */
					}

					if (desc->has_multilines)
					{
						continual_line =  (lnb->lineinfo &&
										   (lnb->lineinfo[i].mask & LINEINFO_CONTINUATION));
					}
				}

				lineno += 1;
			}
			lnb = lnb->next;
		}
	}

	if (lineno != desc->total_rows)
		leave("unexpected processed rows after sort prepare");

	if (detect_string_column)
		sort_column_text(sortbuf, sortbuf_pos, desc_sort);
	else
		sort_column_num(sortbuf, sortbuf_pos, desc_sort);

	lineno = desc->first_data_row;

	for (i = 0; i < sortbuf_pos; i++)
	{
		desc->order_map[lineno].lnb = sortbuf[i].lnb;
		desc->order_map[lineno].lnb_row = sortbuf[i].lnb_row;
		lineno += 1;

		/* assign other continual lines */
		if (desc->has_multilines)
		{
			int		lnb_row;
			bool	continual = false;

			lnb = sortbuf[i].lnb;
			lnb_row = sortbuf[i].lnb_row;

			continual = lnb->lineinfo &&
									   (lnb->lineinfo[lnb_row].mask & LINEINFO_CONTINUATION);

			while (lnb && continual)
			{
				lnb_row += 1;
				if (lnb_row >= lnb->nrows)
				{
					lnb_row = 0;
					lnb = lnb->next;
				}

				desc->order_map[lineno].lnb = lnb;
				desc->order_map[lineno].lnb_row = lnb_row;
				lineno += 1;

				continual = lnb && lnb->lineinfo &&
								(lnb->lineinfo[lnb_row].mask & LINEINFO_CONTINUATION);
			}
		}
	}

	/*
	 * We cannot to say nothing about found_row, so most
	 * correct solution is clean it now.
	 */
	scrdesc->found_row = -1;

	for (i = 0; i < sortbuf_pos; i++)
		free(sortbuf[i].strxfrm);

	free(sortbuf);
}
/*
 * Prepare order map - it is used for printing data in different than
 * original order. "sbcn" - sort by column number
 */
Prepare order map - it is used for printing data in different than
original order. "sbcn" - sort by column number
Prepare order map - it is used for printing data in different than original order . " sbcn " - sort by column number
void
update_order_map(ScrDesc *scrdesc, DataDesc *desc, int sbcn, bool desc_sort)
{
	LineBuffer	   *lnb = &desc->rows;
	char		   *nullstr = NULL;
	int				xmin, xmax;
	int				lineno = 0;
	bool			continual_line = false;
	bool			isnull;
	bool			detect_string_column = false;
	bool			border0 = (desc->border_type == 0);
	SortData	   *sortbuf;
	int				sortbuf_pos = 0;
	int			i;
	xmin = desc->cranges[sbcn - 1].xmin;
	xmax = desc->cranges[sbcn - 1].xmax;
	sortbuf = smalloc(desc->total_rows * sizeof(SortData));
	multilines_detection(desc);
	lnb = &desc->rows;
	lineno = 0;
	sortbuf_pos = 0;
	if (!desc->order_map)
	{
		desc->order_map = smalloc(desc->total_rows * sizeof(MappedLine));
		desc->order_map_items = desc->total_rows;
	}
	while (lnb)
	{
		for (i = 0; i < lnb->nrows; i++)
		{
			desc->order_map[lineno].lnb = lnb;
			desc->order_map[lineno].lnb_row = i;
			if (lineno >= desc->first_data_row && lineno <= desc->last_data_row)
			{
				if (!continual_line)
				{
					sortbuf[sortbuf_pos].lnb = lnb;
					sortbuf[sortbuf_pos].lnb_row = i;
					sortbuf[sortbuf_pos].strxfrm = NULL;
					if (cut_numeric_value(lnb->rows[i],
										   xmin, xmax,
										   &sortbuf[sortbuf_pos].d,
										   border0,
										   &isnull,
										   &nullstr))
						sortbuf[sortbuf_pos++].info = INFO_DOUBLE;
					else
					{
						sortbuf[sortbuf_pos++].info = INFO_UNKNOWN;
						if (!isnull)
						{
							detect_string_column = true;
							goto sort_by_string;
						}
					}
				}
				if (desc->has_multilines)
				{
					continual_line = (lnb->lineinfo &&
									  (lnb->lineinfo[i].mask & LINEINFO_CONTINUATION));
				}
			}
			lineno += 1;
		}
		lnb = lnb->next;
	}
sort_by_string:
	free(nullstr);
	if (detect_string_column)
	{
		lnb = &desc->rows;
		lineno = 0;
		sortbuf_pos = 0;
		while (lnb)
		{
			for (i = 0; i < lnb->nrows; i++)
			{
				desc->order_map[lineno].lnb = lnb;
				desc->order_map[lineno].lnb_row = i;
				if (lineno >= desc->first_data_row && lineno <= desc->last_data_row)
				{
					if (!continual_line)
					{
						sortbuf[sortbuf_pos].lnb = lnb;
						sortbuf[sortbuf_pos].lnb_row = i;
						sortbuf[sortbuf_pos].d = 0.0;
						if (cut_text(lnb->rows[i], xmin, xmax, border0, &sortbuf[sortbuf_pos].strxfrm))
							sortbuf[sortbuf_pos++].info = INFO_STRXFRM;
						else
							sortbuf[sortbuf_pos++].info = INFO_UNKNOWN;		
					}
					if (desc->has_multilines)
					{
						continual_line =  (lnb->lineinfo &&
										   (lnb->lineinfo[i].mask & LINEINFO_CONTINUATION));
					}
				}
				lineno += 1;
			}
			lnb = lnb->next;
		}
	}
	if (lineno != desc->total_rows)
		leave("unexpected processed rows after sort prepare");
	if (detect_string_column)
		sort_column_text(sortbuf, sortbuf_pos, desc_sort);
	else
		sort_column_num(sortbuf, sortbuf_pos, desc_sort);
	lineno = desc->first_data_row;
	for (i = 0; i < sortbuf_pos; i++)
	{
		desc->order_map[lineno].lnb = sortbuf[i].lnb;
		desc->order_map[lineno].lnb_row = sortbuf[i].lnb_row;
		lineno += 1;
		if (desc->has_multilines)
		{
			int		lnb_row;
			bool	continual = false;
			lnb = sortbuf[i].lnb;
			lnb_row = sortbuf[i].lnb_row;
			continual = lnb->lineinfo &&
									   (lnb->lineinfo[lnb_row].mask & LINEINFO_CONTINUATION);
			while (lnb && continual)
			{
				lnb_row += 1;
				if (lnb_row >= lnb->nrows)
				{
					lnb_row = 0;
					lnb = lnb->next;
				}
				desc->order_map[lineno].lnb = lnb;
				desc->order_map[lineno].lnb_row = lnb_row;
				lineno += 1;
				continual = lnb && lnb->lineinfo &&
								(lnb->lineinfo[lnb_row].mask & LINEINFO_CONTINUATION);
			}
		}
	}
	scrdesc->found_row = -1;
	for (i = 0; i < sortbuf_pos; i++)
		free(sortbuf[i].strxfrm);
	free(sortbuf);
}
void update_order_map ( ScrDesc * scrdesc , DataDesc * desc , int sbcn , bool desc_sort ) { LineBuffer * lnb = & desc -> rows ; char * nullstr = NULL ; int xmin , xmax ; int lineno = 0 ; bool continual_line = false ; bool isnull ; bool detect_string_column = false ; bool border0 = ( desc -> border_type == 0 ) ; SortData * sortbuf ; int sortbuf_pos = 0 ; int i ; xmin = desc -> cranges [ sbcn - 1 ] . xmin ; xmax = desc -> cranges [ sbcn - 1 ] . xmax ; sortbuf = smalloc ( desc -> total_rows * sizeof ( SortData ) ) ; multilines_detection ( desc ) ; lnb = & desc -> rows ; lineno = 0 ; sortbuf_pos = 0 ; if ( ! desc -> order_map ) { desc -> order_map = smalloc ( desc -> total_rows * sizeof ( MappedLine ) ) ; desc -> order_map_items = desc -> total_rows ; } while ( lnb ) { for ( i = 0 ; i < lnb -> nrows ; i ++ ) { desc -> order_map [ lineno ] . lnb = lnb ; desc -> order_map [ lineno ] . lnb_row = i ; if ( lineno >= desc -> first_data_row && lineno <= desc -> last_data_row ) { if ( ! continual_line ) { sortbuf [ sortbuf_pos ] . lnb = lnb ; sortbuf [ sortbuf_pos ] . lnb_row = i ; sortbuf [ sortbuf_pos ] . strxfrm = NULL ; if ( cut_numeric_value ( lnb -> rows [ i ] , xmin , xmax , & sortbuf [ sortbuf_pos ] . d , border0 , & isnull , & nullstr ) ) sortbuf [ sortbuf_pos ++ ] . info = INFO_DOUBLE ; else { sortbuf [ sortbuf_pos ++ ] . info = INFO_UNKNOWN ; if ( ! isnull ) { detect_string_column = true ; goto sort_by_string ; } } } if ( desc -> has_multilines ) { continual_line = ( lnb -> lineinfo && ( lnb -> lineinfo [ i ] . mask & LINEINFO_CONTINUATION ) ) ; } } lineno += 1 ; } lnb = lnb -> next ; } sort_by_string : free ( nullstr ) ; if ( detect_string_column ) { lnb = & desc -> rows ; lineno = 0 ; sortbuf_pos = 0 ; while ( lnb ) { for ( i = 0 ; i < lnb -> nrows ; i ++ ) { desc -> order_map [ lineno ] . lnb = lnb ; desc -> order_map [ lineno ] . lnb_row = i ; if ( lineno >= desc -> first_data_row && lineno <= desc -> last_data_row ) { if ( ! continual_line ) { sortbuf [ sortbuf_pos ] . lnb = lnb ; sortbuf [ sortbuf_pos ] . lnb_row = i ; sortbuf [ sortbuf_pos ] . d = 0.0 ; if ( cut_text ( lnb -> rows [ i ] , xmin , xmax , border0 , & sortbuf [ sortbuf_pos ] . strxfrm ) ) sortbuf [ sortbuf_pos ++ ] . info = INFO_STRXFRM ; else sortbuf [ sortbuf_pos ++ ] . info = INFO_UNKNOWN ; } if ( desc -> has_multilines ) { continual_line = ( lnb -> lineinfo && ( lnb -> lineinfo [ i ] . mask & LINEINFO_CONTINUATION ) ) ; } } lineno += 1 ; } lnb = lnb -> next ; } } if ( lineno != desc -> total_rows ) leave ( " " ) ; if ( detect_string_column ) sort_column_text ( sortbuf , sortbuf_pos , desc_sort ) ; else sort_column_num ( sortbuf , sortbuf_pos , desc_sort ) ; lineno = desc -> first_data_row ; for ( i = 0 ; i < sortbuf_pos ; i ++ ) { desc -> order_map [ lineno ] . lnb = sortbuf [ i ] . lnb ; desc -> order_map [ lineno ] . lnb_row = sortbuf [ i ] . lnb_row ; lineno += 1 ; if ( desc -> has_multilines ) { int lnb_row ; bool continual = false ; lnb = sortbuf [ i ] . lnb ; lnb_row = sortbuf [ i ] . lnb_row ; continual = lnb -> lineinfo && ( lnb -> lineinfo [ lnb_row ] . mask & LINEINFO_CONTINUATION ) ; while ( lnb && continual ) { lnb_row += 1 ; if ( lnb_row >= lnb -> nrows ) { lnb_row = 0 ; lnb = lnb -> next ; } desc -> order_map [ lineno ] . lnb = lnb ; desc -> order_map [ lineno ] . lnb_row = lnb_row ; lineno += 1 ; continual = lnb && lnb -> lineinfo && ( lnb -> lineinfo [ lnb_row ] . mask & LINEINFO_CONTINUATION ) ; } } } scrdesc -> found_row = -1 ; for ( i = 0 ; i < sortbuf_pos ; i ++ ) free ( sortbuf [ i ] . strxfrm ) ; free ( sortbuf ) ; }
Prepare order map - it is used for printing data in different than
 original order.
Prepare order map - it is used for printing data in different than original order .
/* multilines should be detected first */ /*
	 * There are two possible sorting methods: numeric or string.
	 * We can try numeric sort first if all values are numbers or
	 * just only one type of string value (like NULL string). This
	 * value can be repeated,
	 *
	 * When there are more different strings, then start again and
	 * use string sort.
	 */ /* read data again and use nls_string */ /* empty string */ /* assign other continual lines */ /*
	 * We cannot to say nothing about found_row, so most
	 * correct solution is clean it now.
	 */