text:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { TextDetailComponent } from './text-detail.component';

describe('TextDetailComponent', () => {
  let component: TextDetailComponent;
  let fixture: ComponentFixture<TextDetailComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ TextDetailComponent ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(TextDetailComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should be created', () => {
    expect(component).toBeTruthy();
  });
});

redpajama_set_name: RedPajamaGithub


text:
// Namespace wpt.moz.main:
window['wpt'] = window['wpt'] || {};
window.wpt['moz'] = window.wpt['moz'] || {};
window.wpt.moz['main'] = window.wpt.moz['main'] || {};

(function() {  // Begin closure

// Running test commands slowly makes debugging easier.
var TEST_TASK_INTERVAL = 5000;

var TASK_INTERVAL = 1000;
var TASK_INTERVAL_SHORT = 0;
var DOM_ELEMENT_POLL_INTERVAL = 100;
var STARTUP_FAILSAFE_INTERVAL = 5000;

var g_active = false;
var g_tabId = -1;
var g_requesting_task = false;
var g_processing_task = false;
var g_started = false;
var g_initialized = false;

// Set to true to pull commands from a static list in fakeCommandSource.js.
var RUN_FAKE_COMMAND_SEQUENCE = false;

// Nuke all of the bookmarks to prevent any live feeds from updating.
// TODO: possibly be more forgiving and query for a list of live bookmarks.
wpt.moz.clearAllBookmarks();

/**
 * Inform the driver that an event occurred.
 */
wpt.moz.main.sendEventToDriver_ = function(eventName, opt_params, opt_data) {
  var url = ('http://127.0.0.1:8888/event/' + eventName);
  if (opt_params) {
    var paramArray = [];
    for (var key in opt_params) {
      paramArray.push(
          encodeURIComponent(key) + '=' + encodeURIComponent(opt_params[key]));
    }
    if (paramArray.length > 0) {
      url = url + '?' + paramArray.join('&');
    }
  }
  wpt.moz.logInfo('POST event:  url = ', url);

  try {
    var xhr = new XMLHttpRequest();
    xhr.open("POST", url, true);
    xhr.send(opt_data);

  } catch (err) {
    wpt.moz.logInfo("Error sending dom element xhr: " + err);
  }

  if (RUN_FAKE_COMMAND_SEQUENCE) {
    // The real driver stops sending commands until an event happens in some
    // cases.  For example, after sending setdomelement, no commands are sent
    // until an event tells the driver that all dom elements loaded.
    // The fake command source needs to know about events to emulate this
    // behavior.
    wpt.fakeCommandSource.onEvent(eventName, opt_params);
  }
};

wpt.moz.main.onStartup = function() {
  if (RUN_FAKE_COMMAND_SEQUENCE) {
    // Run the tasks in FAKE_TASKS.
    window.setInterval(function() {
      var nextCommand = wpt.fakeCommandSource.next();
      if (nextCommand)
        wpt.moz.main.executeTask(nextCommand);
    }, TEST_TASK_INTERVAL);
  } else {
    // Fetch tasks from wptdriver.exe .
    window.setInterval(function() {wpt.moz.main.getTask();}, TASK_INTERVAL);
  }
};

// Monitor for page title changes
// TODO: only track changes for the main browser window (alert boxes will
// fire as well)
(function() {
  var windowMediator = wpt.moz.getService(
      '@mozilla.org/appshell/window-mediator;1',
      'nsIWindowMediator');
  var listener = {
    onWindowTitleChange: function(aWindow, aNewTitle) {
      wpt.moz.main.sendEventToDriver_('title', {'title': aNewTitle});
    },
    onOpenWindow: function(aWindow) {
    },
    onCloseWindow: function(aWindow) {
    }
  };
  windowMediator.addListener(listener);
})();

/**
 * Get notifications from the dialog overlay to log a navigation error when
 * basic auth is required and no credentials have been supplied.
 */
(function() {
  var observerService = Components.classes["@mozilla.org/observer-service;1"].
    getService(Components.interfaces.nsIObserverService);

  var observeUnauthorizedErrors = {
    observe: function(aSubject, aTopic, aData) {
			wpt.moz.main.sendEventToDriver_('navigate_error?error=401');
      g_active = false;
      wptExtension.uninit();
    }
  };

  observerService.addObserver(observeUnauthorizedErrors, "wpt-unauthorised-errors", false);
})();

// Get the next task from the wptdriver.
wpt.moz.main.getTask = function() {
  if (!g_requesting_task && !g_processing_task) {
    g_requesting_task = true;
    try {
      var xhr = new XMLHttpRequest();
      xhr.open('GET', 'http://127.0.0.1:8888/task', true);
      xhr.onreadystatechange = function() {
        if (xhr.readyState == 4) {
          if (xhr.responseText.length > 0) {
            try {
              var resp = JSON.parse(xhr.responseText);
            } catch (err) {
              alert('Error parsing response as JSON: ' +
                    xhr.responseText.substr(0, 120) + '[...]\n');
            }
            if (resp.statusCode == 200 && resp.data) {
              wpt.moz.main.executeTask(resp.data);
            }
          }
        }
      };
      xhr.send();
    } catch (err) {}
    g_requesting_task = false;
  }
};

// Send message that navigation started.
wpt.moz.main.onNavigate = function() {
  wpt.moz.main.sendEventToDriver_('navigate');
  // We used to record the time here, so that events could send
  // a time since navigation.  This was removed: The driver computes
  // times when it receives events.  When firefox implements the web
  // timing spec, consider re-adding it.  Chrome implements the spec,
  // and the chrome extension sends times based on it.
};

// Send onload & W3C navigation timing events.
wpt.moz.main.onLoad = function(win) {
  var win = window.content.document.defaultView.wrappedJSObject;
  g_active = false;
  var fixedViewport = 0;
  if (win.document.querySelector("meta[name=viewport]"))
    fixedViewport = 1;
  var domCount = win.document.getElementsByTagName("*").length;
  wpt.moz.main.sendEventToDriver_('load?fixedViewport=' +
      fixedViewport + '&domCount=' + domCount);
};

/**
 * Fired when gBrowser receives a load event, this function
 * calls wptExtension.loadStop() when a page is ready to call onload
 * handlers.
 */
function onPageLoad(event) {
  if (!g_started) {
    g_started = true;
    wpt.moz.main.onStartup();
  } else {
    // We only care about events aimed at the document.
    if (!event.originalTarget instanceof HTMLDocument)
      return;

    // Filter events from frames by checking that this event references the top
    // window in the page.
    var win = event.originalTarget.defaultView;
    if (!win || win !== win.top)
      return;

    wptExtension.loadStop(win);
  }
}

const STATE_START = Components.interfaces.nsIWebProgressListener.STATE_START;
const STATE_STOP = Components.interfaces.nsIWebProgressListener.STATE_STOP;
var progressListener =
{
  QueryInterface: function(aIID)
  {
   if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
       aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
       aIID.equals(Components.interfaces.nsISupports))
     return this;
   throw Components.results.NS_NOINTERFACE;
  },

  onStateChange: function(aWebProgress, aRequest, aFlag, aStatus) {},
  onLocationChange: function(aProgress, aRequest, aURI) {
		if (aRequest && !Components.isSuccessCode(aRequest.status)) {
			wpt.moz.main.sendEventToDriver_('navigate_error?error=' + aRequest.status);
		}
	},
  onProgressChange: function(aWebProgress, aRequest, curSelf, maxSelf, curTot, maxTot) { },
  onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage) { },
  onSecurityChange: function(aWebProgress, aRequest, aState) { }
}

/**
 * Fired when gBrowser receives a pagehide event, this function
 * calls wptExtension.loadStart() to indicate that navigation is
 * starting.
 */
function onPageHide(event) {
  // We only care about events aimed at the document.
  if (!event.originalTarget instanceof HTMLDocument)
    return;

  var win = event.originalTarget.defaultView;
  if (!win || win !== win.top)
    return;

  wptExtension.loadStart(win);
}

var wptExtension = {
  init: function() {
    // Use the load event on the global browser object to see when the
    // page gets the onload event.
	if (!g_initialized) {
		gBrowser.addEventListener('load', onPageLoad, true);
		gBrowser.addEventListener('pagehide', onPageHide, true);
		gBrowser.addProgressListener(progressListener);
		g_initialized = true;
		setTimeout(function() {
			if (!g_started)
				onPageLoad();
		}, STARTUP_FAILSAFE_INTERVAL);
	}
  },
  uninit: function() {
	if (g_initialized) {
		gBrowser.removeEventListener('load', onPageLoad, true);
		gBrowser.removeEventListener('pagehide', onPageHide, true);
		gBrowser.removeProgressListener(progressListener);
	}
  },
  loadStart: function() {
	wpt.moz.main.onNavigate();
  },
  loadStop: function(win) {
	wpt.moz.main.onLoad(win);
  }
};
window.addEventListener('load', function() { wptExtension.init(); }, false);
window.addEventListener('unload', function() { wptExtension.uninit(); }, false);

// Create a startup failsafe in case the events we attach to have already fired
setTimeout(function() {
	wptExtension.init();
}, STARTUP_FAILSAFE_INTERVAL);

/***********************************************************
                      Utility Functions
***********************************************************/
function trim(stringToTrim) {
  return stringToTrim.replace(/^\s+|\s+$/g, '');
}

/***********************************************************
                      Script Commands
***********************************************************/
wpt.moz.main.callback = function() {
  g_processing_task = false;
  if (!g_active)
    setTimeout(function() {wpt.moz.main.getTask();}, TASK_INTERVAL_SHORT);
}

/** execute a single task/script command */
wpt.moz.main.executeTask = function(task) {
  wpt.moz.logJson('Exec task object: ', task);

  if (task.action && task.action.length) {
    // |task.record| should be named "blocking".  If true, don't ask for
    // another command.
    g_active = !!task.record;
    switch (task.action) {
      case 'navigate':
        wpt.moz.main.navigate(task.target);
        break;
      case 'exec':
        wpt.moz.main.exec(task.target);
        break;
      case 'setcookie':
        wpt.moz.main.setCookie(task.target, task.value);
        break;
      case 'setvalue':
        wpt.moz.main.setValue(task.target, task.value);
        break;
      case 'submitform':
        wpt.moz.main.submitform(task.target);
        break;
      case 'click':
        wpt.moz.main.click(task.target);
        break;
      case 'setinnerhtml':
        wpt.moz.main.setInnerHtml(task.target, task.value);
        break;
      case 'setinnertext':
        wpt.moz.main.setInnerText(task.target, task.value);
        break;
      case 'block':
        wpt.moz.main.block(task.target);
        break;
      case 'setdomelement':
        wpt.moz.main.setDomElement(task.target);
        break;
      case 'collectstats':
        g_processing_task = true;
				var customMetrics = task['target'] || '';
        wpt.moz.main.collectStats(customMetrics, wpt.moz.main.callback);
        break;
      case 'checkresponsive':
        g_processing_task = true;
        wpt.moz.main.checkResponsive(wpt.moz.main.callback);
        break;

      default:
        wpt.moz.logError('Unknown command: ', JSON.stringify(task, null, 2));
    }

    if (!g_active && !g_processing_task) {
      setTimeout(function() {wpt.moz.main.getTask();}, TASK_INTERVAL_SHORT);
    }
  }
};

// exec
wpt.moz.main.exec = function(script) {
  wpt.moz.execScriptInSelectedTab(script, {});
};

// navigate
wpt.moz.main.navigate = function(url) {
  gBrowser.loadURI(url);
};

wpt.moz.main.setCookie = function(cookie_path, data) {
  var pos = data.indexOf(';');
  var val = data;
  var cookie_expires = '';

  if (pos > 0) {
    val = data.substring(0, pos);
    var exp = trim(data.substring(pos + 1));
    pos = exp.indexOf('=');
    if (pos > 0) {
      cookie_expires = trim(exp.substring(pos + 1));
    }
  }
  pos = val.indexOf('=');
  if (pos > 0) {
    var cookie_name = trim(val.substring(0, pos));
    var cookie_value = trim(val.substring(pos + 1));
    if (cookie_name.length && cookie_value.length && cookie_path.length) {
      var cookie = {
        'url': cookie_path,
        'name': cookie_name,
        'value': cookie_value
      };

      if (cookie_expires.length) {
        var date = new Date(cookie_expires);
        cookie['expirationDate'] = date.getTime();
      }
      wpt.moz.setCookie(cookie);
    }
  }
};

/**
 * Run a command that touches the DOM of a page.  The work is done
 * by code in class wpt.contentScript.InPageCommandRunner.  This
 * function should be called within a sandbox, limited to the context
 * of a selected tab.  DON'T use this directly:  Use it by calling
 * SendCommandToContentScript(), which runs it in a sandbox.
 */
function RunCommand_(doc, commandObj) {
  var ipcr = new wpt.contentScript.InPageCommandRunner(
      doc,
      null,  // No chrome API.
      {
        success: function() {
          wpt.moz.logInfo('SUCCESS');
        },
        warn: function() {
          wpt.moz.logInfo('Warn: ',
                          Array.prototype.slice.call(arguments).join(''));
        },
        error: function() {
          wpt.moz.logError(Array.prototype.slice.call(arguments).join(''));
        }
      });
  return ipcr.RunCommand(commandObj);
}

/**
 * Run a command by instantiating an InPageCommandRunner()
 * in a sandbox scoped to the window of the current tab,
 * and passing it an object that specifies a command to invoke.
 */
function SendCommandToContentScript_(commandObj) {
  var exportedFunctions = {
    'RunCommand_': RunCommand_
  };

  var inPageScript = [
      'return RunCommand_(window.document, ', JSON.stringify(commandObj), ');'
  ].join('');

  return wpt.moz.execScriptInSelectedTab(inPageScript, exportedFunctions);
}

wpt.moz.main.setValue = function(target, value) {
  SendCommandToContentScript_({
      'command': 'setValue',
      'target': target,
      'value': value
  });
};

wpt.moz.main.submitform = function(target) {
  SendCommandToContentScript_({
      'command': 'submitForm',
      'target': target
  });
};

wpt.moz.main.click = function(target, value) {
  SendCommandToContentScript_({
      'command': 'click',
      'target': target,
      'value': value
  });
};

wpt.moz.main.setInnerText = function(target, value) {
  SendCommandToContentScript_({
      'command': 'setInnerText',
      'target': target,
      'value': value
  });
};

wpt.moz.main.setInnerHtml = function(target, value) {
  SendCommandToContentScript_({
      'command': 'setInnerHTML',
      'target': target,
      'value': value
  });
};

wpt.moz.main.block = function(target) {
  wpt.moz.blockContentMatching(target);
};

/**
 * The DOM targets we are waiting on.  Used to implement the setDomElement
 * command.
 */
wpt.moz.main.domElementsToWaitOn_ = [];

/**
 * When we are waiting on DOM elements to appear, setInterval is used
 * to poll for them.  The id of that interval is stored here, so that
 * we can cancel it when all DOM elements are found.  When we are not
 * polling, this variable is undefined.
 */
wpt.moz.main.domElementsPollingId_ = undefined;

wpt.moz.main.setDomElement = function(target) {
  wpt.moz.main.domElementsToWaitOn_.push(target);

  // If we are not already polling for the dom elements, start doing so.
  if (typeof(wpt.moz.main.domElementsPollingId_) == 'undefined') {
    wpt.moz.main.domElementsPollingId_ = window.setInterval(
        function() {
          wpt.moz.main.pollForDomElements();
        },
        DOM_ELEMENT_POLL_INTERVAL);
  }
};

wpt.moz.main.pollForDomElements = function() {
  var missingDomElements = [];
  for (var i = 0, ie = wpt.moz.main.domElementsToWaitOn_.length; i < ie; i++) {
    var target = wpt.moz.main.domElementsToWaitOn_[i];
    var targetInPage = SendCommandToContentScript_({
      'command': 'isTargetInDom',
      'target': target
    });

    if (targetInPage) {
      var domElementParams = {
        'name_value': target
      };
      wpt.moz.main.sendEventToDriver_('dom_element', domElementParams);
    } else {
      // If we did not find |target|, save it for the next poll.
      missingDomElements.push(target);
    }
  }

  // Replace the set of dom elements to wait on with the subset that we did
  // not find.
  wpt.moz.main.domElementsToWaitOn_ = missingDomElements;

  // If all targets have been found, stop polling and signal completion.
  if (missingDomElements.length == 0) {
    window.clearInterval(wpt.moz.main.domElementsPollingId_);
    wpt.moz.main.domElementsPollingId_ = undefined;
    wpt.moz.main.sendEventToDriver_('all_dom_elements_loaded', {});
  }
};

wpt.moz.main.collectStats = function(customMetrics, callback) {
  try {
		var win = window.content.document.defaultView.wrappedJSObject;

		// look for any user timing data
		if (win.performance && win.performance.getEntriesByType) {
			var marks = win.performance.getEntriesByType("mark");
			for (var i = 0; i < marks.length; i++) {
				var mark = {"entryType": marks[i].entryType, "name": marks[i].name, "startTime": marks[i].startTime};
				mark.type = 'mark';
				wpt.moz.main.sendEventToDriver_('timed_event', '', JSON.stringify(mark));
			}
			var measures = win.performance.getEntriesByType("measure");
			for (var i = 0; i < measures.length; i++) {
				var measure = {"entryType": measures[i].entryType, "name": measures[i].name, "startTime": measures[i].startTime, "duration": measures[i].duration};
				measure.type = 'measure';
				wpt.moz.main.sendEventToDriver_('timed_event', '', JSON.stringify(measure));
			}
		}

		var domCount = win.document.getElementsByTagName("*").length;
		wpt.moz.main.sendEventToDriver_('domCount', {'domCount':domCount});

		if (win.performance && win.performance.timing) {
			var timingParams = {};
			function addTime(name) {
				if (win.performance.timing[name] > 0) {
					timingParams[name] = Math.max(0, (
							win.performance.timing[name] -
							win.performance.timing['navigationStart']));
				}
			};
			addTime('domInteractive');
			addTime('domContentLoadedEventStart');
			addTime('domContentLoadedEventEnd');
			addTime('loadEventStart');
			addTime('loadEventEnd');
			wpt.moz.main.sendEventToDriver_('window_timing', timingParams);
		}

		// collect any custom metrics
		if (customMetrics.length) {
			var lines = customMetrics.split("\n");
			var lineCount = lines.length;
			var out = {};
			for (var i = 0; i < lineCount; i++) {
				try {
					var parts = lines[i].split(":");
					if (parts.length == 2) {
						var name = parts[0];
						var code = window.atob(parts[1]);
						if (code.length) {
							var script = 'var wptCustomMetric = function() {' + code + '};return wptCustomMetric();'
							var result = wpt.moz.execScriptInSelectedTab(script, {});
							if (typeof result == 'undefined')
								result = '';
							out[name] = result;
						}
					}
				} catch(e){
				}
			}
			wpt.moz.main.sendEventToDriver_('custom_metrics', '', JSON.stringify(out));
		}
  } catch(e){
  }

  if (callback)
    callback();
};

// check to see if any form of the inner width is bigger than the window size (scroll bars)
// default to assuming that the site is responsive and only trigger if we see a case where
// we likely have scroll bars
wpt.moz.main.checkResponsive = function(callback) {
  var win = window.content.document.defaultView.wrappedJSObject;

  var isResponsive = 1;
  var bsw = win.document.body.scrollWidth;
  var desw = win.document.documentElement.scrollWidth;
  var wiw = win.innerWidth;
  if (bsw > wiw)
    isResponsive = 0;
  var nodes = win.document.body.childNodes;
  for (i in nodes) {
    if (nodes[i].scrollWidth > wiw)
      isResponsive = 0;
  }
  wpt.moz.main.sendEventToDriver_('responsive', {'isResponsive':isResponsive});

  if (callback)
    callback();
};

})();  // End closure


text:
#include <asm/errno.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/family.h>
#include <netlink/genl/ctrl.h>
#include <netlink/msg.h>
#include <netlink/attr.h>
#include "internal.h"

struct handler_arg {
	void (*cb)(void *, const char *, int);
	void *priv;
};

static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
			 void *arg)
{
	int *ret = arg;
	*ret = err->error;
	return NL_STOP;
}

static int finish_handler(struct nl_msg *msg, void *arg)
{
	return NL_OK;
}

static int ack_handler(struct nl_msg *msg, void *arg)
{
	int *ret = arg;
	*ret = 0;
	return NL_OK;
}

static int family_handler(struct nl_msg *msg, void *_arg)
{
	struct handler_arg *arg = _arg;
	struct nlattr *tb[CTRL_ATTR_MAX + 1];
	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
	struct nlattr *mcgrp;
	int rem_mcgrp;

	nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
		  genlmsg_attrlen(gnlh, 0), NULL);

	if (!tb[CTRL_ATTR_MCAST_GROUPS])
		return NL_SKIP;

	nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], rem_mcgrp) {
		struct nlattr *tb_mcgrp[CTRL_ATTR_MCAST_GRP_MAX + 1];

		nla_parse(tb_mcgrp, CTRL_ATTR_MCAST_GRP_MAX,
			  nla_data(mcgrp), nla_len(mcgrp), NULL);

		if (!tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME] ||
		    !tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID])
			continue;
		arg->cb(arg->priv,
			nla_data(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]),
			nla_get_u32(tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID]));
	}
	return NL_OK;
}

/**
 * Enumerates the list of available multicast groups for a family
 *
 * \param handle netlink handle to use for querying the list
 * \param family name of family to query for multicast groups
 * \param cbf callback function to call with each multicast group's information.
 * \param priv pointer to pass to the callback function
 *
 * Returns: 0 if ok, < 0 errno code on error.
 *
 * Enumerates the multicast groups available for a generic netlink
 * family and calls the callback with the arguments of each.
 */
int nl_get_multicast_groups(struct nl_sock *handle,
			    const char *family,
			    void (*cbf)(void *, const char *, int),
			    void *priv)
{
	struct nl_msg *msg;
	struct nl_cb *cb;
	int ret, ctrlid;
	struct handler_arg arg = {
		.priv = priv,
		.cb = cbf
	};

	msg = nlmsg_alloc();
	if (!msg)
		return -ENOMEM;

	cb = nl_cb_alloc(NL_CB_DEFAULT);
	if (!cb) {
		ret = -ENOMEM;
		goto out_fail_cb;
	}

	ctrlid = genl_ctrl_resolve(handle, "nlctrl");

	genlmsg_put(msg, 0, 0, ctrlid, 0,
		    0, CTRL_CMD_GETFAMILY, 0);

	ret = -ENOBUFS;
	NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family);

	ret = nl_send_auto_complete(handle, msg);
	if (ret < 0)
		goto out;

	ret = 1;

	nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &ret);
	nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, NULL);
	nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &ret);
	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, family_handler, &arg);

	while (ret > 0)
		ret = nl_recvmsgs(handle, cb);
 nla_put_failure:
 out:
	nl_cb_put(cb);
 out_fail_cb:
	nlmsg_free(msg);
	return ret;
}

int genl_ctrl_get_version(struct nl_sock *nlh, const char *name)
{
	int result;
	struct genl_family *fam;
	struct nl_cache *cache;

	if ((result = genl_ctrl_alloc_cache(nlh, &cache)) < 0)
		return result;

	result = -ENOENT;
	fam = genl_ctrl_search_by_name(cache, name);
	if (fam) {
		result = genl_family_get_version(fam);
		genl_family_put(fam);
	}
	nl_cache_free(cache);
	return result;
}


text:
package org.jkiss.dbeaver.ui.editors.sql.templates;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.text.*;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.templates.TemplateVariable;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;

/**
 * A position based completion proposal.
 *
 * @since 3.0
 */
final class SQLVariableCompletionProposal implements ICompletionProposal, ICompletionProposalExtension2 {

    private TemplateVariable variable;
	/** The string to be displayed in the completion proposal popup */
	private String displayString;
	/** The replacement string */
	private String replacementString;
	/** The replacement position. */
	private Position replacementPosition;
	/** The cursor position after this proposal has been applied */
	private int cursorPosition;
	/** The image to be displayed in the completion proposal popup */
	private Image image;
	/** The context information of this proposal */
	private IContextInformation contextInformation;
	/** The additional info of this proposal */
	private String additionalProposalInfo;

    public SQLVariableCompletionProposal(TemplateVariable variable, String replacementString, Position replacementPosition, int cursorPosition) {
		this(variable, replacementString, replacementPosition, cursorPosition, null, null, null, null);
	}

	public SQLVariableCompletionProposal(TemplateVariable variable, String replacementString, Position replacementPosition, int cursorPosition, Image image, String displayString, IContextInformation contextInformation, String additionalProposalInfo) {
		Assert.isNotNull(replacementString);
		Assert.isTrue(replacementPosition != null);
        this.variable = variable;
		this.replacementString = replacementString;
		this.replacementPosition = replacementPosition;
		this.cursorPosition = cursorPosition;
		this.image = image;
		this.displayString = displayString;
		this.contextInformation = contextInformation;
		this.additionalProposalInfo = additionalProposalInfo;
	}

	/*
	 * @see ICompletionProposal#apply(IDocument)
	 */
	public void apply(IDocument document) {
		try {
			document.replace(replacementPosition.getOffset(), replacementPosition.getLength(), replacementString);
		} catch (BadLocationException x) {
			// ignore
		}
        // Reset variable settings
        if (variable instanceof SQLVariable) {
            SQLVariable sqlVariable = (SQLVariable) variable;
            if (!replacementString.equals(sqlVariable.getCurrentChoice())) {
                sqlVariable.setCurrentChoice(replacementString);
/*
                for (SQLVariable var : sqlVariable.getContext().getVariables()) {
                    if (var != sqlVariable) {
                        TemplateVariableResolver resolver = var.getResolver();
                        if (resolver != null) {
                            resolver.resolve(var, sqlVariable.getContext());
                        }
                    }
                }
*/
            }
        }
    }

	public Point getSelection(IDocument document) {
		return new Point(replacementPosition.getOffset() + cursorPosition, 0);
	}

	public IContextInformation getContextInformation() {
		return contextInformation;
	}

	public Image getImage() {
		return image;
	}

	public String getDisplayString() {
		if (displayString != null)
			return displayString;
		return replacementString;
	}

	public String getAdditionalProposalInfo() {
		return additionalProposalInfo;
	}

	public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {
		apply(viewer.getDocument());
	}

	public void selected(ITextViewer viewer, boolean smartToggle) {
	}

	public void unselected(ITextViewer viewer) {
	}

	public boolean validate(IDocument document, int offset, DocumentEvent event) {
		try {
			String content= document.get(replacementPosition.getOffset(), offset - replacementPosition.getOffset());
			if (replacementString.startsWith(content))
				return true;
		} catch (BadLocationException e) {
			// ignore concurrently modified document
		}
		return false;
	}

}


text:
/**
 * Created by jianxi on 2017/5/12.
 * https://github.com/mabeijianxi
 * mabeijianxi@gmail.com
 */
#include <jni.h>
#include <string>
#include "jx_yuv_encode_h264.h"
#include "jx_pcm_encode_aac.h"
#include "jx_jni_handler.h"
#include "jx_ffmpeg_config.h"
#include "jx_log.h"

using namespace std;

JXYUVEncodeH264 *h264_encoder;
JXPCMEncodeAAC *aac_encoder;

#define VIDEO_FORMAT ".h264"
#define MEDIA_FORMAT ".mp4"
#define AUDIO_FORMAT ".aac"

/**
 * 编码准备,写入配置信息
 */
extern "C"
JNIEXPORT jint JNICALL
Java_com_mabeijianxi_smallvideorecord2_jniinterface_FFmpegBridge_prepareJXFFmpegEncoder(JNIEnv *env,
                                                                                jclass type,
                                                                                jstring media_base_path_,
                                                                                jstring media_name_,
                                                                                jint v_custom_format,
                                                                                jint in_width,
                                                                                jint in_height,
                                                                                jint out_width,
                                                                                jint out_height,
                                                                                jint frame_rate,
                                                                                jlong video_bit_rate) {

    jclass global_class = (jclass) env->NewGlobalRef(type);
    UserArguments *arguments = (UserArguments *) malloc(sizeof(UserArguments));
    const char *media_base_path = env->GetStringUTFChars(media_base_path_, 0);
    const char *media_name = env->GetStringUTFChars(media_name_, 0);
    JXJNIHandler *jni_handler = new JXJNIHandler();
    jni_handler->setup_audio_state(START_STATE);
    jni_handler->setup_video_state(START_STATE);
    arguments->media_base_path = media_base_path;
    arguments->media_name = media_name;

    size_t v_path_size = strlen(media_base_path) + strlen(media_name) + strlen(VIDEO_FORMAT) + 1;
    arguments->video_path = (char *) malloc(v_path_size + 1);

    size_t a_path_size = strlen(media_base_path) + strlen(media_name) + strlen(AUDIO_FORMAT) + 1;
    arguments->audio_path = (char *) malloc(a_path_size + 1);

    size_t m_path_size = strlen(media_base_path) + strlen(media_name) + strlen(MEDIA_FORMAT) + 1;
    arguments->media_path = (char *) malloc(m_path_size + 1);

    strcpy(arguments->video_path, media_base_path);
    strcat(arguments->video_path, "/");
    strcat(arguments->video_path, media_name);
    strcat(arguments->video_path, VIDEO_FORMAT);

    strcpy(arguments->audio_path, media_base_path);
    strcat(arguments->audio_path, "/");
    strcat(arguments->audio_path, media_name);
    strcat(arguments->audio_path, AUDIO_FORMAT);

    strcpy(arguments->media_path, media_base_path);
    strcat(arguments->media_path, "/");
    strcat(arguments->media_path, media_name);
    strcat(arguments->media_path, MEDIA_FORMAT);

    arguments->video_bit_rate = video_bit_rate;
    arguments->frame_rate = frame_rate;
    arguments->audio_bit_rate = 40000;
    arguments->audio_sample_rate = 44100;
    arguments->in_width = in_width;
    arguments->in_height = in_height;
    arguments->out_height = out_height;
    arguments->out_width = out_width;
    arguments->v_custom_format = v_custom_format;
    arguments->handler = jni_handler;
    arguments->env = env;
    arguments->java_class = global_class;
    arguments->env->GetJavaVM(&arguments->javaVM);
    h264_encoder = new JXYUVEncodeH264(arguments);
    aac_encoder = new JXPCMEncodeAAC(arguments);
    int v_code = h264_encoder->initVideoEncoder();
    int a_code = aac_encoder->initAudioEncoder();

    if (v_code == 0 && a_code == 0) {
        return 0;
    } else {
        return -1;
    }

}
/**
 * 编码一帧视频
 */
extern "C"
JNIEXPORT jint JNICALL
Java_com_mabeijianxi_smallvideorecord2_jniinterface_FFmpegBridge_encodeFrame2H264(JNIEnv *env,
                                                                                jclass type,
                                                                                jbyteArray data_) {

    jbyte *elements = env->GetByteArrayElements(data_, 0);
    int i = h264_encoder->startSendOneFrame((uint8_t *) elements);
    env->ReleaseByteArrayElements(data_,elements,0);
    return i;
}

/**
 * 获取ffmpeg编译信息
 */
extern "C"
JNIEXPORT jstring JNICALL
Java_com_mabeijianxi_smallvideorecord2_jniinterface_FFmpegBridge_getFFmpegConfig(JNIEnv *env,
                                                                                jclass type) {

    return getEncoderConfigInfo(env);
}

/**
 * 编码一帧音频
 */
extern "C"
JNIEXPORT jint JNICALL
Java_com_mabeijianxi_smallvideorecord2_jniinterface_FFmpegBridge_encodeFrame2AAC(JNIEnv *env,
                                                                                jclass type,
                                                                                jbyteArray data_) {
    jbyte *elements = env->GetByteArrayElements(data_, 0);
    int i = aac_encoder->sendOneFrame((uint8_t *) elements);
    env->ReleaseByteArrayElements(data_,elements,0);
    return i;
}

/**
 *结束
 */
extern "C"
JNIEXPORT jint JNICALL
Java_com_mabeijianxi_smallvideorecord2_jniinterface_FFmpegBridge_recordEnd(JNIEnv *env,
                                                                           jclass type) {

    if (h264_encoder != NULL) {
        h264_encoder->user_end();
        h264_encoder = NULL;
    }

    if (aac_encoder != NULL) {
        aac_encoder->user_end();
        aac_encoder = NULL;
    }

    return 0;
}

extern "C"
JNIEXPORT void JNICALL
Java_com_mabeijianxi_smallvideorecord2_jniinterface_FFmpegBridge_nativeRelease(JNIEnv *env,
                                                                               jclass type) {

    if (aac_encoder != NULL) {
        try {
            aac_encoder->release();

        } catch (exception e) {

        }
        aac_encoder = NULL;

    }
    if (h264_encoder != NULL) {
        try {
            h264_encoder->release();

        } catch (exception e) {

        }
        h264_encoder = NULL;

    }
}